summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2020-10-31 00:09:22 +0100
committerContext Git Mirror Bot <phg@phi-gamma.net>2020-10-31 00:09:22 +0100
commit7043cd3b7046f6a11112a5d49c4ae5e2dc0c6896 (patch)
tree92ffcd258fb29e37b4a136eb071fbfd0717be29e /tex/context/base/mkiv
parenta0270f13065d116355a953c6f246cbba26289fc2 (diff)
downloadcontext-7043cd3b7046f6a11112a5d49c4ae5e2dc0c6896.tar.gz
2020-10-30 22:27:00
Diffstat (limited to 'tex/context/base/mkiv')
-rw-r--r--tex/context/base/mkiv/anch-pgr.lua4
-rw-r--r--tex/context/base/mkiv/anch-pos.lua15
-rw-r--r--tex/context/base/mkiv/attr-col.lua1
-rw-r--r--tex/context/base/mkiv/attr-eff.mkxl60
-rw-r--r--tex/context/base/mkiv/attr-ini.mkxl143
-rw-r--r--tex/context/base/mkiv/back-exp.lua12
-rw-r--r--tex/context/base/mkiv/back-exp.mkiv8
-rw-r--r--tex/context/base/mkiv/back-ini.mkxl3
-rw-r--r--tex/context/base/mkiv/back-lua.mkxl4
-rw-r--r--tex/context/base/mkiv/back-mps.mkxl4
-rw-r--r--tex/context/base/mkiv/back-out.lmt2
-rw-r--r--tex/context/base/mkiv/back-out.mkxl11
-rw-r--r--tex/context/base/mkiv/back-pdf.mkxl68
-rw-r--r--tex/context/base/mkiv/bibl-tra.mkiv3
-rw-r--r--tex/context/base/mkiv/blob-ini.mkxl14
-rw-r--r--tex/context/base/mkiv/buff-par.mkvi4
-rw-r--r--tex/context/base/mkiv/buff-ver.mkiv8
-rw-r--r--tex/context/base/mkiv/buff-ver.mkxl303
-rw-r--r--tex/context/base/mkiv/catc-ctx.mkiv1
-rw-r--r--tex/context/base/mkiv/catc-ctx.mkxl162
-rw-r--r--tex/context/base/mkiv/catc-ini.mkxl329
-rw-r--r--tex/context/base/mkiv/char-def.lua44
-rw-r--r--tex/context/base/mkiv/char-ini.lua2
-rw-r--r--tex/context/base/mkiv/char-ini.mkiv2
-rw-r--r--tex/context/base/mkiv/char-ini.mkxl130
-rw-r--r--tex/context/base/mkiv/char-tex.lua161
-rw-r--r--tex/context/base/mkiv/chem-str.mkiv2
-rw-r--r--tex/context/base/mkiv/chem-str.mkxl761
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua123
-rw-r--r--tex/context/base/mkiv/cldf-ini.mkiv8
-rw-r--r--tex/context/base/mkiv/cldf-int.mkxl23
-rw-r--r--tex/context/base/mkiv/cldf-lmt.lmt22
-rw-r--r--tex/context/base/mkiv/cldf-scn.lua3
-rw-r--r--tex/context/base/mkiv/colo-ini.mkiv5
-rw-r--r--tex/context/base/mkiv/colo-ini.mkxl352
-rw-r--r--tex/context/base/mkiv/cont-log.mkiv2
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv12
-rw-r--r--tex/context/base/mkiv/cont-run.lua34
-rw-r--r--tex/context/base/mkiv/cont-run.mkiv12
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkxl99
-rw-r--r--tex/context/base/mkiv/core-con.mkiv4
-rw-r--r--tex/context/base/mkiv/core-con.mkxl1013
-rw-r--r--tex/context/base/mkiv/core-dat.mkiv33
-rw-r--r--tex/context/base/mkiv/core-def.mkiv2
-rw-r--r--tex/context/base/mkiv/core-env.lmt193
-rw-r--r--tex/context/base/mkiv/core-env.lua84
-rw-r--r--tex/context/base/mkiv/core-env.mkiv10
-rw-r--r--tex/context/base/mkiv/core-env.mkxl819
-rw-r--r--tex/context/base/mkiv/core-ini.mkiv2
-rw-r--r--tex/context/base/mkiv/driv-shp.lmt16
-rw-r--r--tex/context/base/mkiv/enco-ini.mkiv2
-rw-r--r--tex/context/base/mkiv/enco-ini.mkxl570
-rw-r--r--tex/context/base/mkiv/file-ini.mkvi2
-rw-r--r--tex/context/base/mkiv/file-job.mkvi7
-rw-r--r--tex/context/base/mkiv/file-syn.mklx61
-rw-r--r--tex/context/base/mkiv/font-ctx.lua10
-rw-r--r--tex/context/base/mkiv/font-emp.mklx70
-rw-r--r--tex/context/base/mkiv/font-fea.mklx380
-rw-r--r--tex/context/base/mkiv/font-fil.mklx153
-rw-r--r--tex/context/base/mkiv/font-ini.mklx338
-rw-r--r--tex/context/base/mkiv/font-mat.mklx24
-rw-r--r--tex/context/base/mkiv/font-nod.lua4
-rw-r--r--tex/context/base/mkiv/font-ocm.lua2
-rw-r--r--tex/context/base/mkiv/font-ots.lua302
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv4
-rw-r--r--tex/context/base/mkiv/font-sol.lua4
-rw-r--r--tex/context/base/mkiv/font-sty.mklx109
-rw-r--r--tex/context/base/mkiv/font-sty.mkvi9
-rw-r--r--tex/context/base/mkiv/font-sym.mklx39
-rw-r--r--tex/context/base/mkiv/font-tra.mkiv2
-rw-r--r--tex/context/base/mkiv/grph-epd.lua2
-rw-r--r--tex/context/base/mkiv/grph-fig.mkiv3
-rw-r--r--tex/context/base/mkiv/grph-pat.mkxl119
-rw-r--r--tex/context/base/mkiv/grph-trf.mkiv17
-rw-r--r--tex/context/base/mkiv/hand-ini.mkxl38
-rw-r--r--tex/context/base/mkiv/lang-def.mkiv16
-rw-r--r--tex/context/base/mkiv/lang-dis.lmt222
-rw-r--r--tex/context/base/mkiv/lang-dis.lua2
-rw-r--r--tex/context/base/mkiv/lang-exp.lua2
-rw-r--r--tex/context/base/mkiv/lang-hyp.lmt1806
-rw-r--r--tex/context/base/mkiv/lang-hyp.lua4
-rw-r--r--tex/context/base/mkiv/lang-hyp.mkiv6
-rw-r--r--tex/context/base/mkiv/lang-ini.lmt670
-rw-r--r--tex/context/base/mkiv/lang-ini.lua1
-rw-r--r--tex/context/base/mkiv/lang-ini.mkxl149
-rw-r--r--tex/context/base/mkiv/lang-lab.mkxl95
-rw-r--r--tex/context/base/mkiv/lang-mis.mkiv18
-rw-r--r--tex/context/base/mkiv/lang-mis.mkxl68
-rw-r--r--tex/context/base/mkiv/lang-rep.lua359
-rw-r--r--tex/context/base/mkiv/lang-url.lua10
-rw-r--r--tex/context/base/mkiv/lang-url.mkiv37
-rw-r--r--tex/context/base/mkiv/lang-wrd.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-epa.lua2
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua12
-rw-r--r--tex/context/base/mkiv/luat-cod.lmt6
-rw-r--r--tex/context/base/mkiv/luat-cod.mkxl30
-rw-r--r--tex/context/base/mkiv/luat-fmt.lua5
-rw-r--r--tex/context/base/mkiv/luat-ini.mkiv32
-rw-r--r--tex/context/base/mkiv/luat-lib.mkiv8
-rw-r--r--tex/context/base/mkiv/luat-log.lmt739
-rw-r--r--tex/context/base/mkiv/luat-log.lua795
-rw-r--r--tex/context/base/mkiv/luat-mac.lua66
-rw-r--r--tex/context/base/mkiv/luat-run.lua26
-rw-r--r--tex/context/base/mkiv/luat-usr.mkiv7
-rw-r--r--tex/context/base/mkiv/lxml-ini.mkxl544
-rw-r--r--tex/context/base/mkiv/math-ali.mkxl1893
-rw-r--r--tex/context/base/mkiv/math-def.mkiv10
-rw-r--r--tex/context/base/mkiv/math-fen.mkiv12
-rw-r--r--tex/context/base/mkiv/math-frc.mkiv2
-rw-r--r--tex/context/base/mkiv/math-frc.mkxl753
-rw-r--r--tex/context/base/mkiv/math-ini.lua4
-rw-r--r--tex/context/base/mkiv/math-ini.mkxl648
-rw-r--r--tex/context/base/mkiv/math-noa.lmt2399
-rw-r--r--tex/context/base/mkiv/math-noa.lua10
-rw-r--r--tex/context/base/mkiv/math-pln.mkxl245
-rw-r--r--tex/context/base/mkiv/math-tag.lmt596
-rw-r--r--tex/context/base/mkiv/math-tag.lua4
-rw-r--r--tex/context/base/mkiv/math-toy.mkxl13
-rw-r--r--tex/context/base/mkiv/meta-blb.lua2
-rw-r--r--tex/context/base/mkiv/meta-ini.mkxl406
-rw-r--r--tex/context/base/mkiv/meta-mac.mkxl49
-rw-r--r--tex/context/base/mkiv/mlib-pdf.lua8
-rw-r--r--tex/context/base/mkiv/mlib-pdf.mkxl49
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua16
-rw-r--r--tex/context/base/mkiv/mult-aux.mkxl671
-rw-r--r--tex/context/base/mkiv/mult-def.lua13
-rw-r--r--tex/context/base/mkiv/mult-def.mkiv6
-rw-r--r--tex/context/base/mkiv/mult-fmt.lua2
-rw-r--r--tex/context/base/mkiv/mult-ini.lua86
-rw-r--r--tex/context/base/mkiv/mult-ini.mkxl801
-rw-r--r--tex/context/base/mkiv/mult-low.lua37
-rw-r--r--tex/context/base/mkiv/mult-prm.lua43
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv24
-rw-r--r--tex/context/base/mkiv/mult-sys.mkxl596
-rw-r--r--tex/context/base/mkiv/node-aux.lmt10
-rw-r--r--tex/context/base/mkiv/node-aux.lua10
-rw-r--r--tex/context/base/mkiv/node-cmp.lmt6
-rw-r--r--tex/context/base/mkiv/node-fin.lua97
-rw-r--r--tex/context/base/mkiv/node-fin.mkiv1
-rw-r--r--tex/context/base/mkiv/node-ini.lmt175
-rw-r--r--tex/context/base/mkiv/node-ini.lua39
-rw-r--r--tex/context/base/mkiv/node-ini.mkiv6
-rw-r--r--tex/context/base/mkiv/node-ltp.lua44
-rw-r--r--tex/context/base/mkiv/node-nut.lmt19
-rw-r--r--tex/context/base/mkiv/node-nut.lua11
-rw-r--r--tex/context/base/mkiv/node-par.lmt48
-rw-r--r--tex/context/base/mkiv/node-par.lua6
-rw-r--r--tex/context/base/mkiv/node-ref.lua4
-rw-r--r--tex/context/base/mkiv/node-res.lua22
-rw-r--r--tex/context/base/mkiv/node-rul.lua4
-rw-r--r--tex/context/base/mkiv/node-scn.lua4
-rw-r--r--tex/context/base/mkiv/node-ser.lmt285
-rw-r--r--tex/context/base/mkiv/node-tex.lmt39
-rw-r--r--tex/context/base/mkiv/node-tex.lua9
-rw-r--r--tex/context/base/mkiv/node-tra.lua25
-rw-r--r--tex/context/base/mkiv/pack-box.mkxl1114
-rw-r--r--tex/context/base/mkiv/pack-com.mkxl949
-rw-r--r--tex/context/base/mkiv/pack-lyr.mkxl105
-rw-r--r--tex/context/base/mkiv/pack-mrl.mkxl82
-rw-r--r--tex/context/base/mkiv/pack-ori.mkxl6
-rw-r--r--tex/context/base/mkiv/pack-rul.mkiv6
-rw-r--r--tex/context/base/mkiv/pack-rul.mkxl380
-rw-r--r--tex/context/base/mkiv/page-bck.mkxl715
-rw-r--r--tex/context/base/mkiv/page-ini.mkxl376
-rw-r--r--tex/context/base/mkiv/page-inj.mkvi2
-rw-r--r--tex/context/base/mkiv/page-lay.mkxl1625
-rw-r--r--tex/context/base/mkiv/page-lin.mkvi3
-rw-r--r--tex/context/base/mkiv/page-mcl.mkxl31
-rw-r--r--tex/context/base/mkiv/page-one.mkiv7
-rw-r--r--tex/context/base/mkiv/page-spr.mkxl131
-rw-r--r--tex/context/base/mkiv/page-txt.mklx201
-rw-r--r--tex/context/base/mkiv/phys-dim.mkiv2
-rw-r--r--tex/context/base/mkiv/publ-ini.lua2
-rw-r--r--tex/context/base/mkiv/publ-ini.mkiv34
-rw-r--r--tex/context/base/mkiv/scrn-but.mkvi2
-rw-r--r--tex/context/base/mkiv/scrn-wid.mkvi2
-rw-r--r--tex/context/base/mkiv/spac-ali.mkiv8
-rw-r--r--tex/context/base/mkiv/spac-ali.mkxl357
-rw-r--r--tex/context/base/mkiv/spac-chr.lua2
-rw-r--r--tex/context/base/mkiv/spac-chr.mkiv7
-rw-r--r--tex/context/base/mkiv/spac-grd.mkxl107
-rw-r--r--tex/context/base/mkiv/spac-hor.mkxl479
-rw-r--r--tex/context/base/mkiv/spac-lin.mkiv6
-rw-r--r--tex/context/base/mkiv/spac-par.mkiv3
-rw-r--r--tex/context/base/mkiv/spac-par.mkxl175
-rw-r--r--tex/context/base/mkiv/spac-prf.lua4
-rw-r--r--tex/context/base/mkiv/spac-ver.lmt2623
-rw-r--r--tex/context/base/mkiv/spac-ver.lua81
-rw-r--r--tex/context/base/mkiv/spac-ver.mkiv2
-rw-r--r--tex/context/base/mkiv/spac-ver.mkxl643
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin28214 -> 28808 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin256244 -> 244626 bytes
-rw-r--r--tex/context/base/mkiv/strc-con.mklx1156
-rw-r--r--tex/context/base/mkiv/strc-con.mkvi34
-rw-r--r--tex/context/base/mkiv/strc-des.mklx194
-rw-r--r--tex/context/base/mkiv/strc-enu.mklx375
-rw-r--r--tex/context/base/mkiv/strc-flt.lua6
-rw-r--r--tex/context/base/mkiv/strc-flt.mkvi4
-rw-r--r--tex/context/base/mkiv/strc-itm.mklx212
-rw-r--r--tex/context/base/mkiv/strc-lab.mkxl198
-rw-r--r--tex/context/base/mkiv/strc-lst.mkvi2
-rw-r--r--tex/context/base/mkiv/strc-mat.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-not.mklx1972
-rw-r--r--tex/context/base/mkiv/strc-pag.mkiv21
-rw-r--r--tex/context/base/mkiv/strc-ref.mkvi4
-rw-r--r--tex/context/base/mkiv/strc-reg.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-ren.mkiv6
-rw-r--r--tex/context/base/mkiv/strc-sbe.mkxl139
-rw-r--r--tex/context/base/mkiv/strc-sec.mkiv2
-rw-r--r--tex/context/base/mkiv/strc-sec.mkxl1345
-rw-r--r--tex/context/base/mkiv/strc-syn.mkxl658
-rw-r--r--tex/context/base/mkiv/supp-box.lmt84
-rw-r--r--tex/context/base/mkiv/supp-box.lua4
-rw-r--r--tex/context/base/mkiv/supp-box.mkiv26
-rw-r--r--tex/context/base/mkiv/supp-box.mkxl572
-rw-r--r--tex/context/base/mkiv/supp-ran.lua3
-rw-r--r--tex/context/base/mkiv/symb-imp-cc.mkiv4
-rw-r--r--tex/context/base/mkiv/syst-aux.lmt747
-rw-r--r--tex/context/base/mkiv/syst-aux.lua90
-rw-r--r--tex/context/base/mkiv/syst-aux.mkiv19
-rw-r--r--tex/context/base/mkiv/syst-aux.mkxl1861
-rw-r--r--tex/context/base/mkiv/syst-con.mkxl41
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv34
-rw-r--r--tex/context/base/mkiv/syst-ini.mkxl654
-rw-r--r--tex/context/base/mkiv/syst-lua.lmt23
-rw-r--r--tex/context/base/mkiv/syst-lua.mkiv4
-rw-r--r--tex/context/base/mkiv/syst-lua.mkxl32
-rw-r--r--tex/context/base/mkiv/syst-mac.lmt4
-rw-r--r--tex/context/base/mkiv/syst-mes.mkiv6
-rw-r--r--tex/context/base/mkiv/tabl-com.mkxl69
-rw-r--r--tex/context/base/mkiv/tabl-frm.mkxl261
-rw-r--r--tex/context/base/mkiv/tabl-ltb.mkxl813
-rw-r--r--tex/context/base/mkiv/tabl-mis.mkiv4
-rw-r--r--tex/context/base/mkiv/tabl-ntb.mkxl215
-rw-r--r--tex/context/base/mkiv/tabl-nte.mkiv4
-rw-r--r--tex/context/base/mkiv/tabl-nte.mkxl107
-rw-r--r--tex/context/base/mkiv/tabl-tab.mkiv2
-rw-r--r--tex/context/base/mkiv/tabl-tab.mkxl2229
-rw-r--r--tex/context/base/mkiv/tabl-tbl.lua9
-rw-r--r--tex/context/base/mkiv/tabl-tbl.mkxl633
-rw-r--r--tex/context/base/mkiv/tabl-xnt.mklx142
-rw-r--r--tex/context/base/mkiv/tabl-xtb.mklx983
-rw-r--r--tex/context/base/mkiv/task-ini.lua1
-rw-r--r--tex/context/base/mkiv/toks-aux.lmt241
-rw-r--r--tex/context/base/mkiv/toks-aux.mkiv4
-rw-r--r--tex/context/base/mkiv/toks-ini.lmt12
-rw-r--r--tex/context/base/mkiv/toks-ini.lua3
-rw-r--r--tex/context/base/mkiv/trac-deb.lmt12
-rw-r--r--tex/context/base/mkiv/trac-deb.mkiv8
-rw-r--r--tex/context/base/mkiv/trac-log.lua611
-rw-r--r--tex/context/base/mkiv/trac-vis.lmt1700
-rw-r--r--tex/context/base/mkiv/trac-vis.lua42
-rw-r--r--tex/context/base/mkiv/trac-vis.mkiv26
-rw-r--r--tex/context/base/mkiv/trac-vis.mkxl219
-rw-r--r--tex/context/base/mkiv/type-ini.mklx309
-rw-r--r--tex/context/base/mkiv/typo-bld.lua78
-rw-r--r--tex/context/base/mkiv/typo-brk.lua10
-rw-r--r--tex/context/base/mkiv/typo-chr.lua4
-rw-r--r--tex/context/base/mkiv/typo-dha.lua4
-rw-r--r--tex/context/base/mkiv/typo-dir.mkxl30
-rw-r--r--tex/context/base/mkiv/typo-drp.lua6
-rw-r--r--tex/context/base/mkiv/typo-dua.lua8
-rw-r--r--tex/context/base/mkiv/typo-dub.lua8
-rw-r--r--tex/context/base/mkiv/typo-duc.lua118
-rw-r--r--tex/context/base/mkiv/typo-fln.lua4
-rw-r--r--tex/context/base/mkiv/typo-itc.mkvi4
-rw-r--r--tex/context/base/mkiv/typo-lig.mkxl23
-rw-r--r--tex/context/base/mkiv/typo-lin.lua6
-rw-r--r--tex/context/base/mkiv/typo-mar.mkiv4
-rw-r--r--tex/context/base/mkiv/typo-rub.lua4
271 files changed, 45308 insertions, 7886 deletions
diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua
index be9e28c08..239b33010 100644
--- a/tex/context/base/mkiv/anch-pgr.lua
+++ b/tex/context/base/mkiv/anch-pgr.lua
@@ -76,7 +76,7 @@ local getheight = nuts.getheight
local getdepth = nuts.getdepth
local nodecodes = nodes.nodecodes
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local start_of_par = nuts.start_of_par
local insert_before = nuts.insert_before
@@ -165,7 +165,7 @@ local function flush(head,f,l,a,parent,depth)
ln = new_hlist(setlink(new_rule(65536,65536*4,0),new_kern(-65536),ln))
rn = new_hlist(setlink(new_rule(65536,0,65536*4),new_kern(-65536),rn))
end
- if getid(f) == localpar_code and start_of_par(f) then -- we need to clean this mess
+ if getid(f) == par_code and start_of_par(f) then -- we need to clean this mess
insert_after(head,f,ln)
else
head, f = insert_before(head,f,ln)
diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua
index 554f3fdc0..b2ad5b8b5 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -50,6 +50,7 @@ local ctx_latelua = context.latelua
local tex = tex
local texgetcount = tex.getcount
+local texgetinteger = tex.getintegervalue or tex.getcount
local texsetcount = tex.setcount
local texget = tex.get
local texsp = tex.sp
@@ -282,7 +283,7 @@ local function setall(name,p,x,y,w,h,d,extra)
e = extra ~= "" and extra or nil,
r = region,
c = column,
- r2l = texgetcount("inlinelefttoright") == 1 and true or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 and true or nil,
}
end
@@ -626,7 +627,7 @@ implement {
x = true,
y = true,
n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
@@ -647,7 +648,7 @@ implement {
h = h ~= 0 and h or nil,
d = d ~= 0 and d or nil,
n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
@@ -670,7 +671,7 @@ implement {
h = h ~= 0 and h or nil,
d = d ~= 0 and d or nil,
n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
@@ -692,7 +693,7 @@ implement {
d = d ~= 0 and d or nil,
n = nofparagraphs > 0 and nofparagraphs or nil,
e = scanstring(),
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
@@ -714,7 +715,7 @@ implement {
h = h ~= 0 and h or nil,
d = d ~= 0 and d or nil,
n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
@@ -737,7 +738,7 @@ implement {
h = h ~= 0 and h or nil,
d = d ~= 0 and d or nil,
n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ r2l = texgetinteger("inlinelefttoright") == 1 or nil,
}
tobesaved[name] = spec
ctx_latelua { action = enhance, specification = spec }
diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua
index 88358aeb7..9c542a942 100644
--- a/tex/context/base/mkiv/attr-col.lua
+++ b/tex/context/base/mkiv/attr-col.lua
@@ -445,7 +445,6 @@ function colors.setmodel(name,weightgray)
else
-- stil the same
end
-
return default
end
diff --git a/tex/context/base/mkiv/attr-eff.mkxl b/tex/context/base/mkiv/attr-eff.mkxl
new file mode 100644
index 000000000..04a0c55ce
--- /dev/null
+++ b/tex/context/base/mkiv/attr-eff.mkxl
@@ -0,0 +1,60 @@
+%D \module
+%D [ file=attr-eff,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Effects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Effects}
+
+\registerctxluafile{attr-eff}{}
+
+\unprotect
+
+\installcorenamespace{effect}
+
+\installcommandhandler \??effect {effect} \??effect
+
+\setupeffect
+ [\c!method=\v!none,
+ \c!stretch=\zerocount,
+ \c!rulethickness=\zeropoint,
+ \c!alternative=\v!normal]
+
+\appendtoks
+ \edef\p_method{\effectparameter\c!method}%
+ \ifx\p_method\v!command
+ \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}%
+ \setuxvalue{\e!stop \currenteffect}{\stopeffect}%
+ \fi
+\to \everydefineeffect
+
+\permanent\protected\def\starteffect[#1]%
+ {\clf_seteffect
+ alternative {\namedeffectparameter{#1}\c!alternative}
+ stretch \numexpr\namedeffectparameter{#1}\c!stretch\relax
+ rulethickness \dimexpr\namedeffectparameter{#1}\c!rulethickness\relax
+ \relax}
+
+\permanent\protected\def\stopeffect % can be special
+ {\clf_reseteffect} % v!normal 0 0
+
+\permanent\protected\def\effect[#1]%
+ {\groupedcommand{\starteffect[#1]}{\stopeffect}}
+
+% yes or no grouped
+
+\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt]
+\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt]
+\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt]
+\defineeffect [\v!normal] [\c!alternative=\v!normal]
+\defineeffect [\v!hidden] [\c!alternative=\v!hidden]
+\defineeffect [\v!stretch] [\c!alternative=\v!stretch,\c!stretch=1]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/attr-ini.mkxl b/tex/context/base/mkiv/attr-ini.mkxl
new file mode 100644
index 000000000..d36ad1d0e
--- /dev/null
+++ b/tex/context/base/mkiv/attr-ini.mkxl
@@ -0,0 +1,143 @@
+%D \module
+%D [ file=attr-ini,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Initialization}
+
+%D Although it's still somewhat experimental, here we introduce code
+%D related to attributes. Housekeeping will move completely to \LUA\
+%D and \type {\newattribute} will go away.
+
+\unprotect
+
+\registerctxluafile{attr-ini}{}
+
+\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd)
+\installcorenamespace{attributeid} % the internal number
+\installcorenamespace{attributestack} % the attribute specific stack
+\installcorenamespace{attributepickup}
+
+\permanent\protected\def\pushattribute#1%
+ {\global\advance\csname\??attributestack\string#1\endcsname\plusone
+ \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}}
+
+\permanent\protected\def\popattribute#1%
+ {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax
+ \global\advance\csname\??attributestack\string#1\endcsname\minusone}
+
+\permanent\protected\def\installattributestack#1%
+ {\ifcsname\??attributestack\string#1\endcsname \else
+ \expandafter\newcount\csname\??attributestack\string#1\endcsname
+ \fi}
+
+\newtoks \t_attr_list_global
+\newtoks \t_attr_list_local
+\newtoks \t_attr_list_pickup
+\newtoks \t_attr_list_nomath
+
+\ifdefined \s!global \else \immutable\def\s!global {global} \fi % for metatex % or hard check later
+\ifdefined \s!public \else \immutable\def\s!public {public} \fi % for metatex % or hard check later
+\ifdefined \s!private \else \immutable\def\s!private {private} \fi % for metatex % or hard check later
+\ifdefined \s!attribute \else \immutable\def\s!attribute{attribute} \fi % for metatex % or hard check later
+\ifdefined \s!pickup \else \immutable\def\s!pickup {pickup} \fi % for metatex % or hard check later
+\ifdefined \s!forget \else \immutable\def\s!forget {forget} \fi % for metatex % or hard check later
+
+\immutable\def\??attributeprefix{c_attr_}
+
+\permanent\protected\def\defineattribute {\attr_basics_define_indeed[\s!public ]}
+\permanent\protected\def\definesystemattribute{\attr_basics_define_indeed[\s!private]}
+
+\tolerant\def\attr_basics_define_indeed[#1]#*[#2]#*[#3]%
+ {\ifcsname\??attributeprefix#2\endcsname\else
+ \scratchcounter\clf_defineattribute{#2}{#1}\relax
+ %\writestatus\m!system{defining #1 attribute #2 with number \number\scratchcounter}%
+ \global\expandafter\attributedef\csname\??attributeprefix#2\endcsname\scratchcounter % \foo = 123
+ \global\expandafter\integerdef \csname\??attributeid #2\endcsname\scratchcounter % \attribute\foo = 123
+ % some attributes are always global
+ \doifelseinset\s!global{#3}%
+ {\xtoksapp\t_attr_list_global{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% \c_attr_foo
+ {\xtoksapp\t_attr_list_local {\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}%
+ \doifinset\s!nomath{#3}%
+ {\xtoksapp\t_attr_list_nomath{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}%
+ \doifinset\s!public{#3}%
+ {\aliased\expandafter\glet\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}% \attribute\fooattribute
+ \doifinset\s!pickup{#3}%
+ {\global\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue
+ \xtoksapp\t_attr_list_pickup{\csname\??attributeprefix#2\endcsname\csname\??attributepickup#2\endcsname}%
+ \ifcsname#2\s!attribute\endcsname
+ \expandafter\xdef\csname\s!pickup#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\csname\??attributeprefix#2\endcsname}%
+ \expandafter\xdef\csname\s!forget#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue}%
+ \fi}%
+ \fi}
+
+\permanent\protected\def\pickupattributes
+ {\the\t_attr_list_pickup\relax}
+
+\permanent\protected\def\newattribute#1%
+ {\attr_basics_define_indeed\s!public[\csstring#1][]%
+ \expandafter\glet\expandafter#1\csname\??attributeid\csstring#1\endcsname}
+
+% expandable so we can \edef them for speed
+
+\permanent\def\dosetattribute#1#2{\csname\??attributeprefix#1\endcsname#2\relax}
+\permanent\def\doresetattribute#1{\csname\??attributeprefix#1\endcsname\attributeunsetvalue}
+\permanent\def\dogetattribute #1{\number\csname\??attributeprefix#1\endcsname}
+\permanent\def\dogetattributeid#1{\number\csname\??attributeid #1\endcsname}
+
+\aliased\let\dompattribute\gobbletwoarguments
+
+\permanent\protected\def\resetglobalattributes{\the\t_attr_list_global\glyphdatafield\zerocount\glyphscriptfield\zerocount}
+\permanent\protected\def\resetlocalattributes {\the\t_attr_list_local \glyphdatafield\zerocount\glyphscriptfield\zerocount}
+
+\aliased\let\resetallattributes\resetlocalattributes
+
+%D Rather special.
+
+\permanent\protected\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}}
+\permanent\protected\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}}
+
+%D For the moment we put this here. The order of definition matters a bit because
+%D performance is better when we put frequently accessed attributes at the front.
+%D So, we might move more here.
+
+%definesystemattribute [state] % nomath
+\definesystemattribute [color] [public] % global
+\definesystemattribute [colormodel] [public,global]
+%definesystemattribute [skip]
+%definesystemattribute [penalty]
+\definesystemattribute [transparency] [public]
+\definesystemattribute [reference] [public]
+\definesystemattribute [destination] [public]
+\definesystemattribute [case] [public]
+\definesystemattribute [visual] [public,global]
+\definesystemattribute [viewerlayer] [public]
+\definesystemattribute [background] [public]
+\definesystemattribute [alignbackground] [public]
+\definesystemattribute [colorintent] [public]
+\definesystemattribute [negative] [public]
+\definesystemattribute [effect] [public]
+\definesystemattribute [layoutcomponent] [public]
+\definesystemattribute [internal] [public]
+\definesystemattribute [ruled] [public]
+\definesystemattribute [shifted] [public]
+\definesystemattribute [checkedbreak] [public]
+\definesystemattribute [vboxtohboxseparator] [public]
+
+\permanent\protected\let\showattributes\clf_showattributes % maybe at lua end
+
+%D Todo:
+
+% \appendtoks
+% \clf_cleanupattributes
+% \to \everyafterpagebreak
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua
index f247e4e27..314d66eeb 100644
--- a/tex/context/base/mkiv/back-exp.lua
+++ b/tex/context/base/mkiv/back-exp.lua
@@ -2984,7 +2984,7 @@ local collectresults do -- too many locals otherwise
local kern_code = nodecodes.kern
local disc_code = nodecodes.disc
local whatsit_code = nodecodes.whatsit
- local localpar_code = nodecodes.localpar
+ local par_code = nodecodes.par
local userskip_code = gluecodes.userskip
local rightskip_code = gluecodes.rightskip
@@ -3059,7 +3059,7 @@ local collectresults do -- too many locals otherwise
local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute)
local p
- local localparagraph
+ local paragraph
local maybewrong
local pid
for n, id, subtype in nextnode, head do
@@ -3077,7 +3077,7 @@ local collectresults do -- too many locals otherwise
if last ~= at then
local tl = taglist[at]
local ap = getattr(n,a_taggedpar) or pap
- if localparagraph and (not ap or ap < localparagraph) then
+ if paragraph and (not ap or ap < paragraph) then
maybewrong = addtomaybe(maybewrong,c,1)
end
pushcontent()
@@ -3113,7 +3113,7 @@ local collectresults do -- too many locals otherwise
currentattribute = last
currentparagraph = ap
end
- if localparagraph and (not ap or ap < localparagraph) then
+ if paragraph and (not ap or ap < paragraph) then
maybewrong = addtomaybe(maybewrong,c,2)
end
if trace_export then
@@ -3390,8 +3390,8 @@ end
last = nil
currentparagraph = nil
end
- elseif not localparagraph and id == localpar_code and start_of_par(n) then
- localparagraph = getattr(n,a_taggedpar)
+ elseif not paragraph and id == par_code and start_of_par(n) then
+ paragraph = getattr(n,a_taggedpar)
elseif id == disc_code then
-- very unlikely because we stripped them
local pre, post, replace = getdisc(n)
diff --git a/tex/context/base/mkiv/back-exp.mkiv b/tex/context/base/mkiv/back-exp.mkiv
index 05e404697..23ffdbda0 100644
--- a/tex/context/base/mkiv/back-exp.mkiv
+++ b/tex/context/base/mkiv/back-exp.mkiv
@@ -235,10 +235,10 @@
\to \everyenableelements
\appendtoks
- \let\specialfixedspace \explicitfixedspace
- \let\specialobeyedspace \explicitobeyedspace
- \let\specialstretchedspace\explicitstretchedspace
- \let\specialcontrolspace \explicitcontrolspace
+ \enforced\let\specialfixedspace \explicitfixedspace
+ \enforced\let\specialobeyedspace \explicitobeyedspace
+ \enforced\let\specialstretchedspace\explicitstretchedspace
+ \enforced\let\specialcontrolspace \explicitcontrolspace
\to \everyenableelements
\appendtoks
diff --git a/tex/context/base/mkiv/back-ini.mkxl b/tex/context/base/mkiv/back-ini.mkxl
index 4e2fa351e..00bfeb188 100644
--- a/tex/context/base/mkiv/back-ini.mkxl
+++ b/tex/context/base/mkiv/back-ini.mkxl
@@ -75,7 +75,6 @@
%D \stoptext
%D \stoptyping
-\unexpanded\def\setupoutput[#1]%
- {\clf_enabledriver{#1}}
+\permanent\protected\def\setupoutput[#1]{\clf_enabledriver{#1}}
\protect \endinput
diff --git a/tex/context/base/mkiv/back-lua.mkxl b/tex/context/base/mkiv/back-lua.mkxl
index 6c5aaf82c..0fb1bcc88 100644
--- a/tex/context/base/mkiv/back-lua.mkxl
+++ b/tex/context/base/mkiv/back-lua.mkxl
@@ -11,8 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifcase\contextlmtxmode \else
- \registerctxluafile{back-lua}{autosuffix,optimize}
-\fi
+\registerctxluafile{back-lua}{autosuffix,optimize}
\endinput
diff --git a/tex/context/base/mkiv/back-mps.mkxl b/tex/context/base/mkiv/back-mps.mkxl
index 318b73848..d4d428d42 100644
--- a/tex/context/base/mkiv/back-mps.mkxl
+++ b/tex/context/base/mkiv/back-mps.mkxl
@@ -11,8 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifcase\contextlmtxmode \else
- \registerctxluafile{back-mps}{autosuffix,optimize}
-\fi
+\registerctxluafile{back-mps}{autosuffix,optimize}
\endinput
diff --git a/tex/context/base/mkiv/back-out.lmt b/tex/context/base/mkiv/back-out.lmt
index acf004634..1f33da557 100644
--- a/tex/context/base/mkiv/back-out.lmt
+++ b/tex/context/base/mkiv/back-out.lmt
@@ -43,7 +43,7 @@ local pageliteral_code = literalvalues.page
local directliteral_code = literalvalues.direct
local rawliteral_code = literalvalues.raw
-local immediate_code = tex.prefixcodes.immediate
+local immediate_code = tex.flagcodes.immediate
local nodeproperties = nodes.properties.data
diff --git a/tex/context/base/mkiv/back-out.mkxl b/tex/context/base/mkiv/back-out.mkxl
index 248622c54..9e499a843 100644
--- a/tex/context/base/mkiv/back-out.mkxl
+++ b/tex/context/base/mkiv/back-out.mkxl
@@ -13,11 +13,10 @@
\registerctxluafile{back-out}{autosuffix}
-\let\normalimmediate\immediate
-\let\normalopenout \openout
-\let\normalwrite \write
-\let\normalcloseout \closeout
-\let\normallatelua \latelua
-\let\normalspecial \special
+\let\normalopenout \openout
+\let\normalwrite \write
+\let\normalcloseout\closeout
+\let\normallatelua \latelua
+\let\normalspecial \special
\endinput
diff --git a/tex/context/base/mkiv/back-pdf.mkxl b/tex/context/base/mkiv/back-pdf.mkxl
index b2312bccd..c28352c92 100644
--- a/tex/context/base/mkiv/back-pdf.mkxl
+++ b/tex/context/base/mkiv/back-pdf.mkxl
@@ -56,33 +56,33 @@
%D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably
%D have bad side effects.
-\unexpanded\def\pdfextension{\clf_pdfextension}
- \def\pdffeedback {\clf_pdffeedback}
- \def\pdfvariable {\clf_pdfvariable}
+\permanent\protected\def\pdfextension{\clf_pdfextension}
+\permanent \def\pdffeedback {\clf_pdffeedback}
+\permanent \def\pdfvariable {\clf_pdfvariable}
%D For the moment we keep this for tikz but hopefully it will at some point use
%D the proper ones. Consider them obsolete:
-\unexpanded\def\pdfliteral {\clf_pdfliteral}
-\unexpanded\def\pdfobj {\clf_pdfobj}%
-\unexpanded\def\pdflastobj {\numexpr\clf_pdflastobj\relax}
-\unexpanded\def\pdfrefobj {\clf_pdfrefobj}
+\permanent\protected\def\pdfliteral {\clf_pdfliteral}
+\permanent\protected\def\pdfobj {\clf_pdfobj}%
+\permanent\protected\def\pdflastobj {\numexpr\clf_pdflastobj\relax}
+\permanent\protected\def\pdfrefobj {\clf_pdfrefobj}
-\unexpanded\def\pdfrestore {\pdfextension restore}
-\unexpanded\def\pdfsave {\pdfextension save}
-\unexpanded\def\pdfsetmatrix{\pdfextension setmatrix}
+\permanent\protected\def\pdfrestore {\pdfextension restore}
+\permanent\protected\def\pdfsave {\pdfextension save}
+\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix}
- \let\pdfxform \saveboxresource
- \let\pdflastxform \lastsavedboxresourceindex
- \let\pdfrefxform \useboxresource
+\permanent\let\pdfxform \saveboxresource
+\permanent\let\pdflastxform\lastsavedboxresourceindex
+\permanent\let\pdfrefxform \useboxresource
%D Here are quick and dirty compression flippers, mostly used when testing something
%D as one can best stick to the defaults that also adapt to specific standards.
-\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount}
-\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
-\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine }
-\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree}
+\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount}
+\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
+\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine }
+\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree}
%D PDF/X (maybe combine the two lua calls)
@@ -112,26 +112,26 @@
%D These are the only official methods to add stuff to the resources. If more is
%D needed for third party low level code, it can be added.
-\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}}
-\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}}
-\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}}
+\permanent\protected\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}}
+\permanent\protected\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}}
+\permanent\protected\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}}
-\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}}
-\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}}
-\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}}
+\permanent\protected\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}}
+\permanent\protected\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}}
+\permanent\protected\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}}
-\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}}
-\unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}}
-\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}}
-\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}}
+\permanent\protected\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}}
+\permanent\protected\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}}
+\permanent\protected\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}}
+\permanent\protected\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}}
- \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources}
- \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax}
+\permanent \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources}
+\permanent \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax}
%D This is a temporary hack mthat will be removed, improved or somehow can become
%D default.
-\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
+\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
%D Just in case one needs this \unknown:
%D
@@ -139,7 +139,7 @@
%D text \pdfbackendactualtext{Meier}{Müller} text
%D \stoptyping
-\unexpanded\def\pdfbackendactualtext#1#2% not interfaced
+\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced
{\clf_startactualtext{#2}%
#1%
\clf_stopactualtext}
@@ -149,9 +149,9 @@
%D Bah, this is also needed for tikz:
\ifdefined\pdfsavepos\else
- \let\pdfsavepos \savepos
- \let\pdflastxpos\lastxpos
- \let\pdflastypos\lastypos
+ \permanent\let\pdfsavepos \savepos
+ \permanent\let\pdflastxpos\lastxpos
+ \permanent\let\pdflastypos\lastypos
\fi
\protect \endinput
diff --git a/tex/context/base/mkiv/bibl-tra.mkiv b/tex/context/base/mkiv/bibl-tra.mkiv
index 5389400f3..eebd92d68 100644
--- a/tex/context/base/mkiv/bibl-tra.mkiv
+++ b/tex/context/base/mkiv/bibl-tra.mkiv
@@ -815,9 +815,6 @@
\doifelse{\publicationlistparameter\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}%
\forgetall}
-\unexpanded\def\outdented#1% move to supp-box ?
- {\hskip-\hangindent#1\relax}
-
%D The full list of publications
\unexpanded\def\completepublications
diff --git a/tex/context/base/mkiv/blob-ini.mkxl b/tex/context/base/mkiv/blob-ini.mkxl
index 126319b12..3443836b7 100644
--- a/tex/context/base/mkiv/blob-ini.mkxl
+++ b/tex/context/base/mkiv/blob-ini.mkxl
@@ -28,19 +28,19 @@
% \depthofstring % defined in lua
% \heightanddepthofstring % defined in lua
-\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen
-\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen
-\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen
-\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen
+\permanent\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen
+\permanent\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen
+\permanent\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen
+\permanent\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen
-\let\heightanddepthofstring\totalofstring
-\let\htdpofstring \hdofstring
+\aliased\let\heightanddepthofstring\totalofstring
+\aliased\let\htdpofstring \hdofstring
\let\hd\htdp % if yes then move this
% This one takes anything that can be typeset
-\unexpanded\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}}
+\permanent\protected\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}}
\protect \endinput
diff --git a/tex/context/base/mkiv/buff-par.mkvi b/tex/context/base/mkiv/buff-par.mkvi
index 0ee66dd01..a2d32c6be 100644
--- a/tex/context/base/mkiv/buff-par.mkvi
+++ b/tex/context/base/mkiv/buff-par.mkvi
@@ -65,8 +65,8 @@
\let\buff_parallel_define_saved\defineparallel
\let\buff_parallel_setup_saved \setupparallel
-\unexpanded\def\defineparallel{\dodoubleargument\buff_parallel_define}
-\unexpanded\def\setupparallel {\dotripleargument\buff_parallel_setup}
+\unexpanded\overloaded\def\defineparallel{\dodoubleargument\buff_parallel_define}
+\unexpanded\overloaded\def\setupparallel {\dotripleargument\buff_parallel_setup}
\def\buff_parallel_define[#name][#instances]%
{\buff_parallel_define_saved[#name][\c!list={#instances}]% list is internal
diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv
index 067ae7c39..c9a5c4525 100644
--- a/tex/context/base/mkiv/buff-ver.mkiv
+++ b/tex/context/base/mkiv/buff-ver.mkiv
@@ -287,10 +287,10 @@
\def\buff_verbatim_type_nop
{\buff_verbatim_left_of_type
- \futurelet\next\buff_verbatim_type_one}
+ \futurelet\nexttoken\buff_verbatim_type_one}
\def\buff_verbatim_type_one
- {\ifx\next\bgroup
+ {\ifx\nexttoken\bgroup
\expandafter\buff_verbatim_type_a
\else
\expandafter\buff_verbatim_type_two
@@ -299,10 +299,10 @@
\def\buff_verbatim_type_two
{\catcode`<=\othercatcode % old precaution
\catcode`>=\othercatcode % old precaution
- \futurelet\next\buff_verbatim_type_three}
+ \futurelet\nexttoken\buff_verbatim_type_three}
\def\buff_verbatim_type_three
- {\if\next<%
+ {\if\nexttoken<%
\expandafter\buff_verbatim_type_b
\else
\expandafter\buff_verbatim_type_c
diff --git a/tex/context/base/mkiv/buff-ver.mkxl b/tex/context/base/mkiv/buff-ver.mkxl
index 4dc82288a..9f8a20695 100644
--- a/tex/context/base/mkiv/buff-ver.mkxl
+++ b/tex/context/base/mkiv/buff-ver.mkxl
@@ -42,7 +42,7 @@
\resetbreakpoints
\to \everyinitializeverbatim
-\unexpanded\def\setverbatimspaceskip % to be checked: must happen after font switch
+\permanent\protected\def\setverbatimspaceskip % to be checked: must happen after font switch
{\spaceskip\fontcharwd\font`x\relax
\xspaceskip\spaceskip}
@@ -51,10 +51,10 @@
\setvalue{\??typinglines\v!yes }{\buff_verbatim_obey_breakpoints}
\setvalue{\??typinglines\v!hyphenated}{\buff_verbatim_obey_hyphens}
-\setvalue{\??typingspace\v!on }{\let\obeyedspace\specialcontrolspace}
-\setvalue{\??typingspace\v!stretch }{\let\obeyedspace\specialstretchedspace}
+\setvalue{\??typingspace\v!on }{\enforced\let\obeyedspace\specialcontrolspace}
+\setvalue{\??typingspace\v!stretch }{\enforced\let\obeyedspace\specialstretchedspace}
\setvalue{\??typingspace\v!normal }{}
-\setvalue{\??typingspace\v!fixed }{\let\obeyedspace\specialfixedspace}
+\setvalue{\??typingspace\v!fixed }{\enforced\let\obeyedspace\specialfixedspace}
\setvalue{\??typingblank\v!standard }{\s_spac_whitespace_parskip}
\setvalue{\??typingblank\v!small }{\smallskipamount}
@@ -64,18 +64,18 @@
\setvalue{\??typingblank\v!line }{\baselineskip}
\setvalue{\??typingblank\v!none }{\zeropoint}
-\unexpanded\def\buff_verbatim_obey_hyphens
+\protected\def\buff_verbatim_obey_hyphens
{}
-\unexpanded\def\buff_verbatim_obey_breakpoints
+\protected\def\buff_verbatim_obey_breakpoints
{\language\minusone % tricky as this affects the pagebuilder
\veryraggedright}
-\unexpanded\def\buff_verbatim_ignore_hyphens
+\protected\def\buff_verbatim_ignore_hyphens
{\language\minusone} % tricky as this affects the pagebuilder
\def\buff_verbatim_initialize_type_one
- {\let\obeylines\ignorelines
+ {\enforced\let\obeylines\ignorelines
\edef\p_buff_option{\typeparameter\c!option}%
\ifx\p_buff_option\v!none
\usetypestyleandcolor\c!style\c!color
@@ -88,15 +88,15 @@
\def\buff_verbatim_initialize_type_two
{\spaceskip.5\emwidth\relax
- \let\obeyedspace\specialobeyedspace
- \let\controlspace\specialcontrolspace
+ \enforced\let\obeyedspace\specialobeyedspace
+ \enforced\let\controlspace\specialcontrolspace
\edef\p_buff_lines{\typeparameter\c!lines}%
\begincsname\??typinglines\p_buff_lines\endcsname
\edef\p_buff_space{\typeparameter\c!space}%
\begincsname\??typingspace\p_buff_space\endcsname
\relax\the\everyinitializeverbatim\relax}
-\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
+\protected\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
{\buff_verbatim_initialize_type_one
\buff_verbatim_initialize_type_two}
@@ -130,8 +130,8 @@
\def\buff_verbatim_initialize_typing_two
{\spaceskip.5\emwidth\relax
- \let\obeyedspace\specialobeyedspace
- \let\controlspace\specialcontrolspace
+ \enforced\let\obeyedspace\specialobeyedspace
+ \enforced\let\controlspace\specialcontrolspace
\edef\p_buff_lines{\typingparameter\c!lines}%
\begincsname\??typinglines\p_buff_lines\endcsname
\edef\p_buff_space{\typingparameter\c!space}%
@@ -192,7 +192,7 @@
\def\buff_verbatim_initialize_visualizer#1%
{\ifproductionrun\clf_loadvisualizer{#1}\fi}
-\unexpanded\def\doifelsevisualizer#1%
+\protected\def\doifelsevisualizer#1%
{\clf_doifelsevisualizer{#1}}
\let\doifvisualizerelse\doifelsevisualizer
@@ -264,29 +264,26 @@
{\egroup
\typeparameter\c!right}
-\unexpanded\def\type{\buff_verbatim_type\empty}
-\unexpanded\def\typ {\buff_verbatim_typ \empty}
+\permanent\protected\def\type{\buff_verbatim_type\empty}
+\permanent\protected\def\typ {\buff_verbatim_typ \empty}
-\unexpanded\def\buff_verbatim_type#1%
+\protected\def\buff_verbatim_type#1%
{\dontleavehmode
\bgroup
\edef\currenttype{#1}%
- \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
-
-\def\buff_verbatim_type_yes[#1]%
- {\setupcurrenttype[#1]%
- \buff_verbatim_type_nop}
+ \buff_verbatim_type_indeed}
\def\buff_verbatim_typ#1%
{\dontleavehmode
\bgroup
\edef\currenttype{#1}%
\lettypeparameter\c!lines\v!hyphenated
- \let\specialobeyedspace\specialstretchedspace
- \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop}
+ \enforced\let\specialobeyedspace\specialstretchedspace
+ \buff_verbatim_type_indeed}
-\def\buff_verbatim_type_nop
- {\buff_verbatim_left_of_type
+\tolerant\def\buff_verbatim_type_indeed[#1]%
+ {\ifarguments\or\setupcurrenttype[#1]\fi
+ \buff_verbatim_left_of_type
\futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one}
\def\buff_verbatim_type_one
@@ -369,33 +366,33 @@
%D right, but a decent hyphenation support of \type{\tt} text will be implemented
%D soon.
-\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
-\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
-\unexpanded\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero
-\unexpanded\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback
+\permanent\protected\def\specialfixedspace {\kern\interwordspace\relax}
+\permanent\protected\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
+\permanent\protected\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero
+\permanent\protected\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback
-\unexpanded\def\explicitfixedspace {\asciispacechar}
-\unexpanded\def\explicitobeyedspace {\asciispacechar\allowbreak}
-\unexpanded\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}%
-\unexpanded\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace
+\permanent\protected\def\explicitfixedspace {\asciispacechar}
+\permanent\protected\def\explicitobeyedspace {\asciispacechar\allowbreak}
+\permanent\protected\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}%
+\permanent\protected\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace
\appendtoks
- \unexpanded\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}%
+ \protected\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}%
\to \everyenableelements
-\unexpanded\def\obeyhyphens
- {\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
- \let\controlspace\specialcontrolspace
+\permanent\protected\def\obeyhyphens
+ {\enforced\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
+ \enforced\let\controlspace\specialcontrolspace
\spaceskip.25\emwidth\relax} % hm a bit of stretch !
-\unexpanded\def\obeybreakpoints
+\permanent\protected\def\obeybreakpoints
{\ignorehyphens
\veryraggedright}
-\unexpanded\def\ignorehyphens
+\permanent\protected\def\ignorehyphens
{\language\minusone % extra bonus, the \null should do the job too
- \let\obeyedspace \specialobeyedspace
- \let\controlspace\specialcontrolspace
+ \enforced\let\obeyedspace \specialobeyedspace
+ \enforced\let\controlspace\specialcontrolspace
\spaceskip.5\emwidth\relax}
%D \macros
@@ -427,21 +424,21 @@
\aftergroup\egroup
\let\nexttoken}
-\unexpanded\def\tex{\buff_verbatim_special_type\texescape \relax}
-\unexpanded\def\arg{\buff_verbatim_special_type\leftargument \rightargument}
-\unexpanded\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker}
-\unexpanded\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker}
+\protected\def\tex{\buff_verbatim_special_type\texescape \relax}
+\protected\def\arg{\buff_verbatim_special_type\leftargument \rightargument}
+\protected\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker}
+\protected\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker}
\let\normaltexttex\tex
\let\normaltextarg\arg
\let\normaltextmat\mat
\let\normaltextdis\dis
-\unexpanded\def\astype
+\permanent\protected\def\astype
{\dontleavehmode
\bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
-\unexpanded\def\asciistr#1% used in some old styles
+\permanent\protected\def\asciistr#1% used in some old styles
{\dontleavehmode\begingroup
\dostarttagged\t!verbatim\empty
\usetypestyleandcolor\c!style\c!color\detokenize{#1}%
@@ -454,20 +451,12 @@
\let\beginofverbatimlines\relax % hooks
\let\endofverbatimlines \relax % hooks
-\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
+\protected\def\buff_verbatim_typing_start#1% tricky non standard lookahead
{\begingroup
\edef\currenttyping{#1}%
\obeylines
\futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop}
-\unexpanded\def\buff_verbatim_setup_keep_together
- {\edef\p_keeptogether{\typingparameter\c!keeptogether}%
- \ifx\p_keeptogether\v!yes
- \settrue \c_buff_optimize_linebreaks
- \else
- \setfalse\c_buff_optimize_linebreaks
- \fi}
-
\def\buff_verbatim_typing_start_nop
{\typingparameter\c!before
\startpacked[\v!blank]%
@@ -489,7 +478,17 @@
\buff_verbatim_setup_keep_together
\normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
-\unexpanded\def\buff_verbatim_type_block#1#2%
+% \startnamedtyping[#1]
+
+\protected\def\buff_verbatim_setup_keep_together
+ {\edef\p_keeptogether{\typingparameter\c!keeptogether}%
+ \ifx\p_keeptogether\v!yes
+ \settrue \c_buff_optimize_linebreaks
+ \else
+ \setfalse\c_buff_optimize_linebreaks
+ \fi}
+
+\protected\def\buff_verbatim_type_block#1#2%
{\edef\p_strip{\typingparameter\c!strip}%
\normalexpanded{\buff_pickup
{_typing_}%
@@ -499,7 +498,7 @@
{\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}%
\ifx\p_strip\v!no\zerocount\else\plusone\fi}}
-\unexpanded\def\buff_verbatim_type_block_verbatim_indeed#1#2%
+\protected\def\buff_verbatim_type_block_verbatim_indeed#1#2%
{\buff_verbatim_initialize_typing_two
\dostarttaggedchained\t!verbatimblock\currenttyping\??typing
\beginofverbatimlines
@@ -518,7 +517,7 @@
\dostoptagged
\begincsname#2\endcsname}
-\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
+\protected\def\buff_verbatim_typing_stop#1% hm, currenttyping
{\stoppacked
\typingparameter\c!after
\useindentnextparameter\typingparameter
@@ -578,27 +577,49 @@
% [category] [settings] {name} % for historic reasons, all filenames are {}
-\unexpanded\def\typefile
- {\dodoubleempty\buff_verbatim_type_file}
-
\appendtoks
\setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}%
\to \everydefinetyping
-\def\buff_verbatim_type_file[#1][#2]#3%
+%% \protected\def\typefile
+%% {\dodoubleempty\buff_verbatim_type_file}
+%%
+%% \def\buff_verbatim_type_file[#1][#2]#3%
+%% {\begingroup
+%% \ifsecondargument
+%% \setuptyping[#1][#2]%
+%% \buff_verbatim_type_file_checked{#1}{#3}%
+%% \orelse\iffirstargument
+%% \ifcondition\validassignment{#1}%
+%% \setuptyping[\v!file][#1]%
+%% \buff_verbatim_type_file_checked\v!file{#3}%
+%% \else
+%% \buff_verbatim_type_file_checked{#1}{#3}%
+%% \fi
+%% \else
+%% \buff_verbatim_type_file_checked\v!file{#3}%
+%% \fi
+%% \useindentnextparameter\typingparameter % needs checking
+%% \endgroup
+%% \dorechecknextindentation} % needs checking
+
+\permanent\tolerant\protected\def\typefile[#1]#*[#2]%
+ {\buff_verbatim_type_file{#1}{#2}}
+
+\def\buff_verbatim_type_file#1#2#3%
{\begingroup
- \ifsecondargument
- \setuptyping[#1][#2]%
- \buff_verbatim_type_file_checked{#1}{#3}%
- \orelse\iffirstargument
+ \ifarguments
+ \buff_verbatim_type_file_checked\v!file{#3}%
+ \or
\ifcondition\validassignment{#1}%
\setuptyping[\v!file][#1]%
\buff_verbatim_type_file_checked\v!file{#3}%
\else
\buff_verbatim_type_file_checked{#1}{#3}%
\fi
- \else
- \buff_verbatim_type_file_checked\v!file{#3}%
+ \or
+ \setuptyping[#1][#2]%
+ \buff_verbatim_type_file_checked{#1}{#3}%
\fi
\useindentnextparameter\typingparameter % needs checking
\endgroup
@@ -609,7 +630,7 @@
{\buff_verbatim_type_file_indeed{#1}\askedtypingfile}
{\showmessage\m!verbatims1{#2}}}
-\unexpanded\def\doifelsetypingfile#1%
+\permanent\protected\def\doifelsetypingfile#1%
{\edef\askedtypingfile{\locfilename{#1}}%
\ifempty\askedtypingfile
\edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible
@@ -620,7 +641,7 @@
\expandafter\firstoftwoarguments
\fi}
-\let\doiftypingfileelse\doifelsetypingfile
+\aliased\let\doiftypingfileelse\doifelsetypingfile
\def\buff_verbatim_type_file_indeed#1#2% category name
{\edef\currenttyping{#1}%
@@ -651,7 +672,7 @@
\newconditional\verbatimnumberinglines
-\def\beginofverbatimlinenumbering
+\permanent\protected\def\beginofverbatimlinenumbering
{\startlinenumbering
[\currenttyping]%
[\c!continue=\typingparameter\c!continue,
@@ -660,7 +681,7 @@
\c!stop=\typingparameter\c!stop, % ?
\c!step=\typingparameter\c!step]}
-\def\endofverbatimlinenumbering
+\overloaded\protected\def\endofverbatimlinenumbering
{\stoplinenumbering}
\def\buff_verbatim_setup_line_numbering
@@ -675,8 +696,8 @@
\setfalse\verbatimnumberinglines
\fi
\ifconditional\verbatimnumberinglines
- \let\beginofverbatimlines\beginofverbatimlinenumbering
- \let\endofverbatimlines \endofverbatimlinenumbering
+ \enforced\let\beginofverbatimlines\beginofverbatimlinenumbering
+ \enforced\let\endofverbatimlines \endofverbatimlinenumbering
\fi
\fi}
@@ -691,14 +712,14 @@
%D
%D The definition is not that spectacular.
-\unexpanded\def\filename#1{{\tttf\hyphenatedfilename{#1}}}
+\permanent\protected\def\filename#1{{\tttf\hyphenatedfilename{#1}}}
%D \macros
%D {verbatim}
%d
%D And a bonus macro, an unexpanded detokenize:
-\unexpanded\def\verbatim#1{\detokenize{#1}}
+\permanent\protected\def\verbatim#1{\detokenize{#1}}
%D The setups for display verbatim and file verbatim are shared. One can adapt the
%D extra defined typing environments, but they also default to the values below.
@@ -762,18 +783,12 @@
% [name] [settings] | [name] | [settings]
-% \unexpanded\def\typebuffer
-% {\dodoubleempty\buff_verbatim_type_buffer}
-
-\unexpanded\def\typebuffer
+\permanent\protected\def\typebuffer
{\begingroup
\let\currenttyping\v!buffer
- \dodoubleempty\buff_verbatim_type_buffer}
-
-\unexpanded\def\buff_verbatim_type_defined_buffer
- {\dotripleempty\buff_verbatim_type_defined_buffer_indeed}
+ \buff_verbatim_type_buffer}
-\unexpanded\def\typedefinedbuffer[#1]%
+\protected\def\typedefinedbuffer[#1]%
{\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}%
\appendtoks
@@ -784,32 +799,32 @@
\setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}%
\to \everydefinetyping
-\unexpanded\def\buff_verbatim_type_buffer[#1][#2]%
- {\ifsecondargument
- \setupcurrenttyping[#2]%
- \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings]
- \orelse\iffirstargument
- \ifcondition\validassignment{#1}%
+\tolerant\protected\def\buff_verbatim_type_buffer[#1]#*[#2]%
+ {\ifarguments
+ \buff_verbatim_type_buffer_indeed\currenttyping\empty% []
+ \or
+ \ifhastok={#1}%
\setupcurrenttyping[#1]%
\buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings]
\else
\processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name]
\fi
- \else
- \buff_verbatim_type_buffer_indeed\currenttyping\empty% []
+ \or
+ \setupcurrenttyping[#2]%
+ \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings]
\fi
\useindentnextparameter\typingparameter
\endgroup
\dorechecknextindentation}
-\unexpanded\def\buff_verbatim_type_buffer_class#1%
+\protected\def\buff_verbatim_type_buffer_class#1%
{\begingroup
\edef\currenttyping{#1}%
- \dodoubleempty\buff_verbatim_type_buffer}
+ \buff_verbatim_type_buffer}
-\unexpanded\def\buff_verbatim_type_defined_buffer_indeed[#1][#2][#3]% category name settings
+\tolerant\protected\def\buff_verbatim_type_defined_buffer[#1]#*[#2]#*[#3]% category name settings
{\begingroup
- \ifthirdargument
+ \ifarguments\or\or\or
\setuptyping[#1][#3]%
\fi
\buff_verbatim_type_buffer_indeed{#1}{#2}%
@@ -817,7 +832,7 @@
\endgroup
\dorechecknextindentation}
-\unexpanded\def\buff_verbatim_type_buffer_indeed#1#2% category name
+\protected\def\buff_verbatim_type_buffer_indeed#1#2% category name
{\edef\currenttyping{#1}%
\typingparameter\c!before
\startpacked[\v!blank]
@@ -843,15 +858,15 @@
\stoppacked
\typingparameter\c!after}
-\unexpanded\def\typeinlinebuffer
+\permanent\protected\def\typeinlinebuffer
{\dontleavehmode
\begingroup
\let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline
\let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code
\let\currenttype\empty
- \dodoubleempty\buff_verbatim_type_buffer}
+ \buff_verbatim_type_buffer}
-\unexpanded\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name
+\protected\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name
{\edef\currenttype{#1}%
\buff_verbatim_initialize_type_one
\dostarttaggedchained\t!verbatim\currenttype\??type
@@ -871,24 +886,22 @@
% the next one is obsolete (bad name and used nowhere) so if it stays
% the name will change
-\unexpanded\def\processbuffer
+\permanent\tolerant\protected\def\processbuffer[#1]#*[#2]%
{\writestatus{nota bene}{\string\processbuffer\space is obsolete}%
- \dodoubleempty\buff_verbatim_process}
-
-\def\buff_verbatim_process[#1][#2]%
- {\begingroup
- \ifsecondargument
- \setuptyping[\v!buffer][#2]%
- \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
- \orelse\iffirstargument
- \ifcondition\validassignment{#1}%
+ \begingroup
+ \ifarguments
+ \buff_verbatim_process_indeed\v!buffer\empty% []
+ \or
+ %\ifcondition\validassignment{#1}%
+ \ifhastok={#1}%
\setuptyping[\v!buffer][#1]%
\buff_verbatim_process_indeed\v!buffer\empty% [settings]
\else
\processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name]
\fi
- \else
- \buff_verbatim_process_indeed\v!buffer\empty% []
+ \or
+ \setuptyping[\v!buffer][#2]%
+ \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
\fi
\endgroup}
@@ -908,7 +921,7 @@
\newcount\nofverbatimlines
-\unexpanded\def\buff_verbatim_begin_of_line
+\protected\def\buff_verbatim_begin_of_line
{\ifconditional\verbatimnumberinglines
\global\advance\nofverbatimlines\plusone
\c_attr_verbatimline\nofverbatimlines
@@ -917,10 +930,9 @@
\buff_verbatim_set_line_margin
\the\everyline % maybe also after starttagged
\strut % after starttagged, else break !
- \dostarttagged\t!verbatimline\empty
- }
+ \dostarttagged\t!verbatimline\empty}
-\unexpanded\def\buff_verbatim_end_of_line
+\protected\def\buff_verbatim_end_of_line
{\dostoptagged
\obeyedline % still needed?
\par
@@ -928,7 +940,7 @@
\c_attr_verbatimline\attributeunsetvalue
\fi}
-\unexpanded\def\buff_verbatim_empty_line
+\protected\def\buff_verbatim_empty_line
{\dostoptagged
\ifconditional\verbatimnumberinglines
\par\strut\par % this will be an option where we use a signal instead of a strut
@@ -937,7 +949,7 @@
\fi
\dostarttagged\t!verbatimlines\empty}
-% hooks:
+% hooks (todo: frozen):
\newcount \c_buff_verbatim_noflines
\newcount \c_buff_verbatim_current
@@ -945,25 +957,25 @@
\def\doverbatimspace {\obeyedspace}
-\unexpanded\def\doinlineverbatimstart {}
-\unexpanded\def\doinlineverbatimstop {}
-\unexpanded\def\doinlineverbatimbeginline {}
-\unexpanded\def\doinlineverbatimnewline {\obeyedspace}
-\unexpanded\def\doinlineverbatimemptyline {\obeyedspace}
-
-\unexpanded\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone
- \buff_verbatim_begin_of_line}
-\unexpanded\def\dodisplayverbatimstop {\buff_verbatim_end_of_line}
-\unexpanded\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone
- \buff_verbatim_begin_of_line}
-\unexpanded\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line
- \par
- \ifconditional\c_buff_optimize_linebreaks
- \buff_verbatim_inject_breaks
- \fi}
-\unexpanded\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line}
-
-\unexpanded\def\buff_verbatim_inject_breaks
+\protected\def\doinlineverbatimstart {}
+\protected\def\doinlineverbatimstop {}
+\protected\def\doinlineverbatimbeginline {}
+\protected\def\doinlineverbatimnewline {\obeyedspace}
+\protected\def\doinlineverbatimemptyline {\obeyedspace}
+
+\protected\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\protected\def\dodisplayverbatimstop {\buff_verbatim_end_of_line}
+\protected\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone
+ \buff_verbatim_begin_of_line}
+\protected\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line
+ \par
+ \ifconditional\c_buff_optimize_linebreaks
+ \buff_verbatim_inject_breaks
+ \fi}
+\protected\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line}
+
+\protected\def\buff_verbatim_inject_breaks
{\ifnum\c_buff_verbatim_current=\plusone
\nobreak
\orelse\ifnum\c_buff_verbatim_noflines=\plusthree
@@ -972,7 +984,7 @@
\nobreak
\fi}
-\unexpanded\def\dodisplayverbatiminitialize#1%
+\protected\def\dodisplayverbatiminitialize#1%
{\forgetparindent % maybe more
\c_buff_verbatim_noflines#1\relax
\c_buff_verbatim_current\zerocount}
@@ -991,22 +1003,21 @@
% \setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}%
% \to \everydefinevisualizer
%
-% \unexpanded\def\buff_verbatim_visualize#1%
+% \protected\def\buff_verbatim_visualize#1%
% {\bgroup
% \def\currentvisualizer{#1}%
% \usevisualizerstyleandcolor\c!style\c!color
% \let\next}
\appendtoks
- %def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
- \def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize
- \def\tex #1{\letterbackslash#1}%
+ \enforced\def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize
+ \enforced\def\tex #1{\letterbackslash#1}%
\to \everysimplifycommands
\stopcontextdefinitioncode
%D This is \type {\asciimode} without the double comment hackery:
-\unexpanded\def\literalmode{\setcatcodetable\txtcatcodes}
+\protected\def\literalmode{\setcatcodetable\txtcatcodes}
\protect \endinput
diff --git a/tex/context/base/mkiv/catc-ctx.mkiv b/tex/context/base/mkiv/catc-ctx.mkiv
index 3492a4bc5..c86201a78 100644
--- a/tex/context/base/mkiv/catc-ctx.mkiv
+++ b/tex/context/base/mkiv/catc-ctx.mkiv
@@ -125,6 +125,7 @@
\catcodetable \ctxcatcodes
\let \defaultcatcodetable \ctxcatcodes
+% \defaultcatcodetable \ctxcatcodes % also an option
% for the moment here:
diff --git a/tex/context/base/mkiv/catc-ctx.mkxl b/tex/context/base/mkiv/catc-ctx.mkxl
new file mode 100644
index 000000000..fcaec65d0
--- /dev/null
+++ b/tex/context/base/mkiv/catc-ctx.mkxl
@@ -0,0 +1,162 @@
+%D \module
+%D [ file=catc-cys,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Extra Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D We prefer to define relevant catcode tables in this file instead
+%D of everywhere around.
+
+\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi
+\ifdefined \prtcatcodes \else \newcatcodetable \prtcatcodes \fi
+\ifdefined \txtcatcodes \else \newcatcodetable \txtcatcodes \fi
+%ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky
+\ifdefined \tpacatcodes \else \newcatcodetable \tpacatcodes \fi % { }
+\ifdefined \tpbcatcodes \else \newcatcodetable \tpbcatcodes \fi % < >
+
+\setnewconstant \doublecommentsignal "10FF25 %% < 110000 (last valid range)
+
+\startcatcodetable \ctxcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ % \catcode\circumflexasciicode\superscriptcatcode
+ % \catcode\underscoreasciicode\subscriptcatcode
+ % \catcode\ampersandasciicode \alignmentcatcode
+ \catcode\underscoreasciicode\othercatcode
+ \catcode\circumflexasciicode\othercatcode
+ \catcode\ampersandasciicode \othercatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+\startcatcodetable \prtcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode % candidate
+ \catcode\underscoreasciicode \lettercatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode \endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+\startcatcodetable \tpacatcodes
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode \othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode \othercatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+\stopcatcodetable
+
+\startcatcodetable \tpbcatcodes
+ \catcode\tabasciicode \othercatcode
+ \catcode\endoflineasciicode \othercatcode
+ \catcode\formfeedasciicode \othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\endoffileasciicode \othercatcode
+ \catcode\lessthanasciicode \begingroupcatcode
+ \catcode\morethanasciicode \endgroupcatcode
+\stopcatcodetable
+
+\startcatcodetable \txtcatcodes
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\doublecommentsignal\commentcatcode
+\stopcatcodetable
+
+\letcatcodecommand \ctxcatcodes \barasciicode \relax
+\letcatcodecommand \ctxcatcodes \tildeasciicode \relax
+
+\pushoverloadmode
+
+ \catcodetable \ctxcatcodes
+\let \defaultcatcodetable \ctxcatcodes
+
+\popoverloadmode
+
+% for the moment here:
+
+\permanent\protected\def\starttexcode
+ {\pushcatcodetable
+ \catcodetable\prtcatcodes}
+
+\permanent\protected\def\stoptexcode
+ {\popcatcodetable}
+
+\permanent\protected\def\startcontextcode
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes}
+
+\permanent\protected\def\stopcontextcode
+ {\popcatcodetable}
+
+% not visible, only for special cases
+
+\newcatcodetable \ctdcatcodes % context definitions
+
+\startcatcodetable \ctdcatcodes
+ \catcode\tabasciicode \ignorecatcode
+ \catcode\endoflineasciicode \ignorecatcode
+ \catcode\formfeedasciicode \ignorecatcode
+ \catcode\spaceasciicode \ignorecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode % candidate
+ \catcode\underscoreasciicode \lettercatcode
+ \catcode\ampersandasciicode \alignmentcatcode
+% \catcode\colonasciicode \lettercatcode % candidate
+ \catcode\backslashasciicode \escapecatcode
+ \catcode\leftbraceasciicode \begingroupcatcode
+ \catcode\rightbraceasciicode \endgroupcatcode
+ \catcode\dollarasciicode \mathshiftcatcode
+ \catcode\hashasciicode \parametercatcode
+ \catcode\commentasciicode \commentcatcode
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\tildeasciicode \activecatcode
+ \catcode\barasciicode \activecatcode
+\stopcatcodetable
+
+\permanent\protected\def\startcontextdefinitioncode
+ {\pushcatcodetable
+ \catcodetable\ctdcatcodes}
+
+\permanent\protected\def\stopcontextdefinitioncode
+ {\popcatcodetable}
+
+\endinput
diff --git a/tex/context/base/mkiv/catc-ini.mkxl b/tex/context/base/mkiv/catc-ini.mkxl
new file mode 100644
index 000000000..fb1b5b359
--- /dev/null
+++ b/tex/context/base/mkiv/catc-ini.mkxl
@@ -0,0 +1,329 @@
+%D \module
+%D [ file=catc-ini,
+%D version=2006.09.18,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Catcode Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%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.
+
+\registerctxluafile{catc-ini}{}
+
+\unprotect
+
+%D A long standing wish has been the availability of catcode arrays. Because
+%D traditional \TEX\ does not provide this we implement a fake method in the
+%D \MKII\ file. There is some overlap in code with \MKII\ but we take that
+%D for granted. Also, in \MKIV\ less active characters are used.
+
+% \begingroup
+%
+% \catcode\tabasciicode \activecatcode
+% \catcode\formfeedasciicode \activecatcode
+% \catcode\endoflineasciicode\activecatcode
+%
+% \letcharcode\tabasciicode \relax
+% \letcharcode\newlineasciicode \relax
+% \letcharcode\formfeedasciicode \relax
+% \letcharcode\endoflineasciicode\relax
+%
+% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I}
+% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J}
+% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L}
+% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M}
+%
+% \endgroup
+
+\begingroup
+ \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode}
+\endgroup
+
+% \endlinechar = \endoflineasciicode % appended to input lines
+% \newlinechar = \newlineasciicode % can be used in write
+
+% 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
+ \newlinechar\newlineasciicode
+ \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>>}
+
+\installsystemnamespace {catcodelet} % let : \let
+\installsystemnamespace {catcodedef} % def : \def
+\installsystemnamespace {catcodeued} % ued : \protected\def
+\installsystemnamespace {catcodeget} % \meaning
+
+\installsystemnamespace {catcodetablet}
+\installsystemnamespace {catcodetablen}
+
+\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate
+\newcount\c_syst_catcodes_a
+\newcount\c_syst_catcodes_b
+\newcount\c_syst_catcodes_c
+
+\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua
+ {\global\advance\c_syst_catcodes_n\plusone
+ \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
+ %\setnewconstant#1\c_syst_catcodes_n
+ \overloaded\integerdef#1\c_syst_catcodes_n
+ \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}}
+
+\newtoks \everysetdefaultcatcodes
+
+\everysetdefaultcatcodes % this might get dropped
+ {\catcode\backslashasciicode\othercatcode
+ \catcode\endoflineasciicode\othercatcode
+ \catcode\spaceasciicode \othercatcode
+ \catcode\commentasciicode \othercatcode
+ \catcode\delasciicode \othercatcode}
+
+\permanent\protected\def\startcatcodetable#1#2\stopcatcodetable
+ {\begingroup
+ \catcodetable\inicatcodes
+ \the\everysetdefaultcatcodes
+ #2%
+ \savecatcodetable#1\relax
+ \endgroup}
+
+\permanent\let\stopcatcodetable\relax
+
+\permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+ {\begingroup
+ \catcodetable#1\relax
+ \globaldefs\plusone
+ #2%
+ \globaldefs\zerocount
+ \endgroup}
+
+\permanent\let\stopextendcatcodetable\relax
+
+\permanent\protected\def\permitcircumflexescape % to be used grouped
+ {\catcode\circumflexasciicode\superscriptcatcode}
+
+\let\permitcaretescape\permitcircumflexescape
+
+% ==
+%
+% \protected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+% {\bgroup
+% \scratchcounter\the\catcodetable
+% \catcodetable #1 #2
+% \catcodetable\scratchcounter
+% \egroup}
+
+%D The next command can be defined in a cleaner way in the MkIV way but we want
+%D to have a fast one with a minimal chance for interference. Do we still need
+%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use
+%D active characters for very special cases.
+
+\setnewconstant\c_syst_catcodes_hack\tildeasciicode
+
+%D Once a catcode is assigned, the next assignments will happen faster. However,
+%D redefinitions probably happen seldom so it's sort of overkill.
+
+\permanent\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a}
+\permanent\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a}
+\permanent\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a}
+
+\def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b}
+\def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b}
+\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b}
+
+\def\syst_catcodes_let_b % each time
+ {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_let_c
+ \fi}
+
+\def\syst_catcodes_def_b % each time
+ {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_def_c
+ \fi}
+
+\def\syst_catcodes_ued_b % each time
+ {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\syst_catcodes_ued_c
+ \fi}
+
+\def\syst_catcodes_let_c % only first time
+ {\frozen\enforced\global\expandafter\def\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
+ {\enforced\expandafter\let\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here)
+ {\frozen\enforced\global\expandafter\def\csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\frozen\enforced\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_normal
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\def\syst_catcodes_ued_c % only first time
+ {\frozen\enforced\global\expandafter\def\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\frozen\enforced\protected\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\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)
+
+\def\syst_catcodes_reinstate_normal
+ {\begingroup
+ \edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}%
+ \global\letcharcode\c_syst_catcodes_b\c_syst_char_code
+ \endgroup}
+
+\def\syst_catcodes_reinstate_unexpanded
+ {\begingroup
+ \protected\edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}%
+ \global\letcharcode\c_syst_catcodes_b\c_syst_char_code
+ \endgroup}
+
+\newconstant\defaultcatcodetable
+
+\permanent\def\catcodecommand#1%
+ {\csname\??catcodeget\number
+ \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname
+ \currentcatcodetable \else \defaultcatcodetable
+ \fi
+ :\number#1\endcsname}
+
+%D \macros
+%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.
+
+\newcount\c_syst_catcodes_level
+
+\permanent\protected\def\pushcatcodetable
+ {\advance\c_syst_catcodes_level\plusone
+ \syst_catcodes_trace_push
+ \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
+
+\permanent\protected\def\popcatcodetable
+ {\ifcase\c_syst_catcodes_level
+ \syst_catcodes_trace_nesting_error
+ \else
+ \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname
+ \syst_catcodes_trace_pop
+ \advance\c_syst_catcodes_level\minusone
+ \fi}
+
+\protected\def\syst_catcodes_trace_nesting_error
+ {\immediate\write\statuswrite{}%
+ \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end
+ \immediate\write\statuswrite{}}
+
+\permanent\protected\def\restorecatcodes % takes previous level
+ {\ifnum\c_syst_catcodes_level>\plusone
+ \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:
+%D
+%D \starttyping
+%D \tracecatcodetables
+%D \stoptyping
+
+\permanent\protected\def\tracecatcodetables
+ {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \number\c_syst_catcodes_level}}%
+ \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}%
+ \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}}
+
+\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}}
+
+\def\syst_catcodes_prev
+ {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount
+ \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
+ \else
+ -%
+ \fi}
+
+\def\catcodetablename
+ {\ifnum\currentcatcodetable>\zerocount
+ \csname\??catcodetablen\number\currentcatcodetable\endcsname
+ \else
+ -%
+ \fi}
+
+\let\syst_catcodes_trace_set \empty
+\let\syst_catcodes_trace_push\empty
+\let\syst_catcodes_trace_pop \empty
+
+% \tracecatcodetables
+
+\protect
+
+%D We still have to define these so let's do that now:
+
+\newcatcodetable \inicatcodes
+\initcatcodetable\inicatcodes
+
+\let\currentcatcodetable\catcodetable
+
+\endinput
diff --git a/tex/context/base/mkiv/char-def.lua b/tex/context/base/mkiv/char-def.lua
index 51a227cb5..70e564399 100644
--- a/tex/context/base/mkiv/char-def.lua
+++ b/tex/context/base/mkiv/char-def.lua
@@ -429,7 +429,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="binary",
- mathname="ast",
+--mathname="ast",
mathsymbol=0x2217,
synonyms={ "star" },
unicodeslot=0x2A,
@@ -4893,7 +4893,7 @@ characters.data={
{
adobename="Vhook",
category="lu",
- contextname="Uhook",
+ contextname="Vhook",
description="LATIN CAPITAL LETTER V WITH HOOK",
direction="l",
lccode=0x28B,
@@ -10546,7 +10546,7 @@ characters.data={
direction="l",
linebreak="al",
mathclass="ordinary",
- mathname="varkappa",
+--mathname="varkappa",
specials={ "compat", 0x3BA },
uccode=0x39A,
unicodeslot=0x3F0,
@@ -58794,7 +58794,6 @@ characters.data={
[0x1EF6]={
adobename="Yhookabove",
category="lu",
- contextname="Yhook",
description="LATIN CAPITAL LETTER Y WITH HOOK ABOVE",
direction="l",
lccode=0x1EF7,
@@ -58806,7 +58805,6 @@ characters.data={
[0x1EF7]={
adobename="yhookabove",
category="ll",
- contextname="yhook",
description="LATIN SMALL LETTER Y WITH HOOK ABOVE",
direction="l",
linebreak="al",
@@ -60767,7 +60765,7 @@ characters.data={
},
[0x1FBB]={
category="lu",
- contextname="greekAlphatonos",
+ comment="conflict: greekAlphatonos",
description="GREEK CAPITAL LETTER ALPHA WITH OXIA",
direction="l",
lccode=0x1F71,
@@ -60897,7 +60895,7 @@ characters.data={
},
[0x1FC9]={
category="lu",
- contextname="greekEpsilontonos",
+ comment="conflict: greekEpsilontonos",
description="GREEK CAPITAL LETTER EPSILON WITH OXIA",
direction="l",
lccode=0x1F73,
@@ -60919,7 +60917,7 @@ characters.data={
},
[0x1FCB]={
category="lu",
- contextname="greekEtatonos",
+ comment="conflict: greekEtatonos",
description="GREEK CAPITAL LETTER ETA WITH OXIA",
direction="l",
lccode=0x1F75,
@@ -60950,7 +60948,7 @@ characters.data={
},
[0x1FCE]={
category="sk",
- contextname="greekpsilitonos",
+ comment="conflict: greekpsilitonos",
description="GREEK PSILI AND OXIA",
direction="on",
linebreak="al",
@@ -61000,7 +60998,7 @@ characters.data={
},
[0x1FD3]={
category="ll",
- contextname="greekiotadialytikatonos",
+ comment="conflict: greekiotadialytikatonos",
description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA",
direction="l",
linebreak="al",
@@ -61063,7 +61061,7 @@ characters.data={
},
[0x1FDB]={
category="lu",
- contextname="greekIotatonos",
+ comment="conflict: greekIotatonos",
description="GREEK CAPITAL LETTER IOTA WITH OXIA",
direction="l",
lccode=0x1F77,
@@ -61083,7 +61081,7 @@ characters.data={
},
[0x1FDE]={
category="sk",
- contextname="greekdasiatonos",
+ comment="conflict: greekdasiatonos",
description="GREEK DASIA AND OXIA",
direction="on",
linebreak="al",
@@ -61133,7 +61131,7 @@ characters.data={
},
[0x1FE3]={
category="ll",
- contextname="greekupsilondialytikatonos",
+ comment="conflict: greekupsilondialytikatonos",
description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA",
direction="l",
linebreak="al",
@@ -61217,7 +61215,7 @@ characters.data={
},
[0x1FEB]={
category="lu",
- contextname="greekUpsilontonos",
+ comment="conflict: greekUpsilontonos",
description="GREEK CAPITAL LETTER UPSILON WITH OXIA",
direction="l",
lccode=0x1F7B,
@@ -61248,7 +61246,7 @@ characters.data={
},
[0x1FEE]={
category="sk",
- contextname="greekdialytikatonos",
+ comment="conflict: greekdialytikatonos",
description="GREEK DIALYTIKA AND OXIA",
direction="on",
linebreak="al",
@@ -61328,7 +61326,7 @@ characters.data={
},
[0x1FF9]={
category="lu",
- contextname="greekOmicrontonos",
+ comment="conflict: greekOmicrontonos",
description="GREEK CAPITAL LETTER OMICRON WITH OXIA",
direction="l",
lccode=0x1F79,
@@ -61350,7 +61348,7 @@ characters.data={
},
[0x1FFB]={
category="lu",
- contextname="greekOmegatonos",
+ comment="conflict: greekOmegatonos",
description="GREEK CAPITAL LETTER OMEGA WITH OXIA",
direction="l",
lccode=0x1F7D,
@@ -63212,10 +63210,10 @@ characters.data={
direction="nsm",
linebreak="cm",
mathspec={
- {
- class="default",
- name="bigcircle",
- },
+-- {
+-- class="default",
+-- name="bigcircle",
+-- },
{
class="binary",
name="bigcircle",
@@ -65221,7 +65219,7 @@ characters.data={
[0x21B5]={
adobename="carriagereturn",
category="so",
- contextname="carriagereturn",
+ comment="conflict: carriagereturn",
description="DOWNWARDS ARROW WITH CORNER LEFTWARDS",
direction="on",
linebreak="al",
@@ -135799,7 +135797,7 @@ characters.data={
},
[0xFDF9]={
category="lo",
- contextname="arabicsalla",
+ comment="conflict: arabicsalla",
description="ARABIC LIGATURE SALLA ISOLATED FORM",
direction="al",
linebreak="al",
diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua
index 58882cd30..1f8e72af7 100644
--- a/tex/context/base/mkiv/char-ini.lua
+++ b/tex/context/base/mkiv/char-ini.lua
@@ -766,7 +766,7 @@ local is_mark = allocate ( tohash {
} )
local is_punctuation = allocate ( tohash {
- "pc","pd","ps","pe","pi","pf","po",
+ "pc", "pd", "ps", "pe", "pi", "pf", "po",
} )
local is_symbol = allocate ( tohash {
diff --git a/tex/context/base/mkiv/char-ini.mkiv b/tex/context/base/mkiv/char-ini.mkiv
index 5979b8685..aa3d31ba8 100644
--- a/tex/context/base/mkiv/char-ini.mkiv
+++ b/tex/context/base/mkiv/char-ini.mkiv
@@ -125,6 +125,8 @@
\clf_setactivecatcodes\notcatcodes
\clf_setactivecatcodes\prtcatcodes
+\clf_setcharacternames\ctxcatcodes
+
\def\chardescription#1{\clf_chardescription#1\relax}
% experiment (watch out: this is global and very font dependent when used with
diff --git a/tex/context/base/mkiv/char-ini.mkxl b/tex/context/base/mkiv/char-ini.mkxl
new file mode 100644
index 000000000..1df5d4b01
--- /dev/null
+++ b/tex/context/base/mkiv/char-ini.mkxl
@@ -0,0 +1,130 @@
+%D \module
+%D [ file=char-ini,
+%D version=2006.08.20,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Character Support / Initialization}
+
+\registerctxluafile{char-fio}{}
+\registerctxluafile{char-map}{} % maybe we will load this someplace else
+\registerctxluafile{char-tex}{}
+\registerctxluafile{char-ent}{}
+
+\unprotect
+
+% ¨äëïöüÿ
+% ´áćéíĺńóŕśúýź
+% ˙ċėġiż
+% ¯āēīōū
+% ˝őű
+% ˆâĉêĝĥîĵôŝûŵŷ
+% `àèìòùỳ
+% ¸çķļņŗşţ
+% ˛ąęįų
+% ˚åů
+% ˘ăĕğĭŏŭ
+% ˇčďěľňřšťž
+% ˜ãĩñõũ
+
+% \def\checkedchar#1% #2%
+% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
+%
+% impossible in math mode so there always fallback (till we have gyre):
+%
+% use \normalUchar when possible .. the next one is nice for documents and it also accepts
+% 0x prefixed numbers
+
+\permanent\def\utfchar #1{\clf_utfchar {#1}} % todo: define public at lua end
+\permanent\def\safechar#1{\clf_safechar{#1}} % todo: define public at lua end
+
+\permanent\protected\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded)
+\permanent \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded)
+
+\permanent\def\expandUx{\enforced\let\Ux\eUx}
+
+\permanent \def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2
+\permanent \def\checkedmathchar#1#2{#2}
+%permanent \def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
+\permanent\protected\def\checkedtextchar #1{\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2}
+
+\newconditional\prefermathovertextchar
+
+\permanent\protected\def\textormathchar#1%
+ {\begingroup
+ \scratchcounter#1\relax
+ \ifmmode
+ \char\scratchcounter
+ \else
+ \ifconditional\prefermathovertextchar
+ % dirty trick .. maybe let this adapt to bf too ?
+ \setfontid\fontid\textfont\c_font_fam_mr
+ \fi
+ \iffontchar\font\scratchcounter
+ \char\scratchcounter
+ \else
+ \normalstartimath\char\scratchcounter\normalstopimath
+ \fi
+ \fi
+ \endgroup}
+
+\permanent\protected\def\textormathchars#1%
+ {{\font_text_or_mathchars#1\relax}}
+
+\protected\def\font_text_or_mathchars#1#2\relax
+ {\relax\ifmmode
+ #1#2%
+ \orelse\iffontchar\font`#1\relax
+ #1#2\relax
+ \else
+ \normalstartimath#1#2\normalstopimath
+ \fi}
+
+%D The codes are stored in the format, so we don't need to reinitialize
+%D them (unless of course we have adapted the table). It is on the agenda
+%D to do this with \type {tex.lccode} cum suis once they're available.
+
+% \def\setcclcuc#1#2#3{\global\catcode#1=\lettercatcode\global\lccode#1=#2\global\uccode#1=#3\relax}
+% \def\setcclcucself#1{\global\catcode#1=\lettercatcode\global\lccode#1=#1\global\uccode#1=#1\relax }
+
+% Is setting up vrb tpa and tpb needed?
+
+% move to lua side
+
+%clf_setcharactercodes
+
+\clf_setlettercatcodes\texcatcodes
+\clf_setlettercatcodes\ctxcatcodes
+\clf_setlettercatcodes\notcatcodes
+%clf_setlettercatcodes\mthcatcodes
+\clf_setlettercatcodes\vrbcatcodes
+\clf_setlettercatcodes\prtcatcodes
+\clf_setlettercatcodes\tpacatcodes
+\clf_setlettercatcodes\tpbcatcodes
+\clf_setlettercatcodes\txtcatcodes
+
+\clf_setactivecatcodes\ctxcatcodes
+\clf_setactivecatcodes\notcatcodes
+\clf_setactivecatcodes\prtcatcodes
+
+\clf_setcharacternames\ctxcatcodes
+
+\permanent\def\chardescription#1{\clf_chardescription#1\relax}
+
+% experiment (watch out: this is global and very font dependent when used with
+% casing mechanisms)
+%
+% \overloaduppercase{0xDF}{0x1E9E}}
+% \overloaduppercase{0xDF}{0x53,0x53}
+
+\permanent\protected\def\overloaduppercase{\clf_overloaduppercase} % todo: define public at lua end
+\permanent\protected\def\overloadlowercase{\clf_overloadlowercase} % todo: define public at lua end
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/char-tex.lua b/tex/context/base/mkiv/char-tex.lua
index b361a9a07..1e86ca171 100644
--- a/tex/context/base/mkiv/char-tex.lua
+++ b/tex/context/base/mkiv/char-tex.lua
@@ -573,88 +573,68 @@ if not csletters then
local traditional = sfstate == "traditional"
for u, chr in next, data do -- will move up
- local fallback = chr.fallback
- if fallback then
- contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}")
- activated[#activated+1] = u
- else
- local contextname = chr.contextname
- local category = chr.category
- local isletter = is_letter[category]
- if contextname then
- if is_character[category] then
- if chr.unicodeslot < 128 then
- if isletter then
- local c = utfchar(u)
- texsetmacro(contextname,c)
- csletters[c] = u
- else
- texsetchar(contextname,u)
- end
- else
- local c = utfchar(u)
- texsetmacro(contextname,c)
- if isletter and u >= 32 and u <= 65536 then
- csletters[c] = u
- end
- end
- --
+ local contextname = chr.contextname
+ local category = chr.category
+ local isletter = is_letter[category]
+ if contextname then
+ if is_character[category] then
+ if chr.unicodeslot < 128 then
if isletter then
- local lc = chr.lccode
- local uc = chr.uccode
- if not lc then
- chr.lccode = u
- lc = u
- elseif type(lc) == "table" then
- lc = u
- end
- if not uc then
- chr.uccode = u
- uc = u
- elseif type(uc) == "table" then
- uc = u
- end
- texsetlccode(u,lc,uc)
- if traditional and category == "lu" then
- texsetsfcode(code,999)
- end
+ local c = utfchar(u)
+ csletters[c] = u
end
- --
- elseif is_command[category] and not forbidden[u] then
- -- contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\",contextname,"}}")
- -- activated[#activated+1] = u
+ else
local c = utfchar(u)
- texsetmacro(contextname,c)
- elseif is_mark[category] then
- texsetlccode(u,u,u) -- for hyphenation
- end
- -- elseif isletter and u >= 32 and u <= 65536 then
- elseif isletter then
- csletters[utfchar(u)] = u
- --
- local lc, uc = chr.lccode, chr.uccode
- if not lc then
- chr.lccode = u
- lc = u
- elseif type(lc) == "table" then
- lc = u
- end
- if not uc then
- chr.uccode = u
- uc = u
- elseif type(uc) == "table" then
- uc = u
+ if isletter and u >= 32 and u <= 65536 then
+ csletters[c] = u
+ end
end
- texsetlccode(u,lc,uc)
- if traditional and category == "lu" then
- texsetsfcode(code,999)
+ if isletter then
+ local lc = chr.lccode
+ local uc = chr.uccode
+ if not lc then
+ chr.lccode = u
+ lc = u
+ elseif type(lc) == "table" then
+ lc = u
+ end
+ if not uc then
+ chr.uccode = u
+ uc = u
+ elseif type(uc) == "table" then
+ uc = u
+ end
+ texsetlccode(u,lc,uc)
+ if traditional and category == "lu" then
+ texsetsfcode(code,999)
+ end
end
- --
+ elseif is_command[category] and not forbidden[u] then
+ -- skip
elseif is_mark[category] then
- --
texsetlccode(u,u,u) -- for hyphenation
- --
end
+ elseif isletter then
+ csletters[utfchar(u)] = u
+ local lc, uc = chr.lccode, chr.uccode
+ if not lc then
+ chr.lccode = u
+ lc = u
+ elseif type(lc) == "table" then
+ lc = u
+ end
+ if not uc then
+ chr.uccode = u
+ uc = u
+ elseif type(uc) == "table" then
+ uc = u
+ end
+ texsetlccode(u,lc,uc)
+ if traditional and category == "lu" then
+ texsetsfcode(code,999)
+ end
+ elseif is_mark[category] then
+ texsetlccode(u,u,u) -- for hyphenation
end
end
@@ -690,6 +670,29 @@ if not csletters then
storage.register("characters/csletters", csletters, "characters.csletters")
end
+ function characters.setcharacternames(ctt)
+ for u, chr in next, data do -- will move up
+ local contextname = chr.contextname
+ local category = chr.category
+ local isletter = is_letter[category]
+ if contextname then
+ if is_character[category] then
+ if chr.unicodeslot < 128 then
+ if isletter then
+ texsetmacro(contextname,utfchar(u),"permanent")
+ else
+ texsetchar(contextname,u)
+ end
+ else
+ texsetmacro(contextname,utfchar(u),"permanent")
+ end
+ elseif is_command[category] and not forbidden[u] then
+ texsetmacro(contextname,utfchar(u),"permanent")
+ end
+ end
+ end
+ end
+
else
mark(csletters)
end
@@ -826,9 +829,13 @@ end
-- entities.gt = utfchar(characters.activeoffset + utfbyte(">"))
-- end
-implement { name = "setlettercatcodes", scope = "private", actions = characters.setlettercatcodes, arguments = "integer" }
-implement { name = "setactivecatcodes", scope = "private", actions = characters.setactivecatcodes, arguments = "integer" }
---------- { name = "setcharactercodes", scope = "private", actions = characters.setcodes }
+if characters.setcharacternames then -- only in ini mode
+
+ implement { name = "setlettercatcodes", scope = "private", actions = characters.setlettercatcodes, arguments = "integer" }
+ implement { name = "setactivecatcodes", scope = "private", actions = characters.setactivecatcodes, arguments = "integer" }
+ implement { name = "setcharacternames", scope = "private", actions = characters.setcharacternames, arguments = "integer" }
+
+end
-- experiment (some can move to char-ini.lua)
diff --git a/tex/context/base/mkiv/chem-str.mkiv b/tex/context/base/mkiv/chem-str.mkiv
index 71b104e47..17c80472e 100644
--- a/tex/context/base/mkiv/chem-str.mkiv
+++ b/tex/context/base/mkiv/chem-str.mkiv
@@ -449,7 +449,7 @@
\egroup}
\appendtoks
- \let|\chemicalbar % \SR{N|NH}
+ \let |\chemicalbar % \SR{N|NH}
\let \+\chemicaloxidationplus
\let \-\chemicaloxidationminus
\let \[\chemicalforeveropen
diff --git a/tex/context/base/mkiv/chem-str.mkxl b/tex/context/base/mkiv/chem-str.mkxl
new file mode 100644
index 000000000..853887678
--- /dev/null
+++ b/tex/context/base/mkiv/chem-str.mkxl
@@ -0,0 +1,761 @@
+%D \module
+%D [ file=chem-ini,
+%D version=2009.05.13,
+%D subtitle=Chemistry,
+%D author=Hans Hagen \& Alan Braslau,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+%D but better implementation, later versions might provide more,
+
+%D NOT YET LMTX'd
+
+\writestatus{loading}{ConTeXt Chemistry Macros / Structure}
+
+\registerctxluafile{chem-str}{}
+
+% We have a slightly different interface. This is unchanged:
+%
+% \startchemical[axis=on]
+% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1]
+% \stopchemical
+%
+% Here we use chemicalformula instead, so no longer a mix:
+%
+% \startchemicalformula
+% \chemical{2H_2}{top}{bottom}
+% \chemical{PLUS}{top}{bottom}
+% \chemical{O_2}{top}{bottom}
+% \chemical{GIVES}{top}{bottom}
+% \chemical{2H_2O}{top}{bottom}
+% \stopchemicalformula
+%
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+%
+% The inline variant has only one argument:
+%
+% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O}
+
+\unprotect
+
+\installcorenamespace{chemical}
+\installcorenamespace{chemicalsymbol}
+\installcorenamespace{chemicalframed}
+\installcorenamespace{chemicalsize}
+
+% \installsimplecommandhandler \??chemical {chemical} \??chemical % no \define...
+\installcommandhandler \??chemical {chemical} \??chemical % no \define...
+
+\let\setupchemicals \setupchemical
+\let\definechemicals\definechemical
+
+%D We use a dedicated framed macro instead of inheriting one. This is both
+%D a historical and practical reason (like shared keys with different meaning
+%D that could clash, e.g.\ align).
+
+\defineMPinstance % not really needed as we set in lua
+ [chemistry]
+ [\s!format=metafun,
+ %\s!extensions=\v!yes, % Should we add extensions and initializations?
+ %\s!initializations=\v!yes, % Would this give EmWidth, etc.?
+ \c!method=\s!double]
+
+\startMPdefinitions{chemistry}
+ loadmodule "chem" ;
+\stopMPdefinitions
+
+\defineframed
+ [\??chemicalframed]
+ [\c!align=\v!normal,
+ \c!strut=\v!no]
+
+\unexpanded\def\setupchemicalframed
+ {\setupframed[\??chemicalframed]}
+
+\unexpanded\overloaded\def\definechemical % is global (so we don't use the commandhandler)
+ {\dosingleargument\chem_define}
+
+\def\chem_define[#1]#2%
+ {\startnointerference
+ \edef\currentdefinedchemical{#1}%
+ \let\chemical\chem_chemical_nested
+ \clf_undefinechemical{#1}%
+ #2% flush
+ \stopnointerference}
+
+\unexpanded\def\chem_chemical_nested
+ {\dodoubleempty\chem_chemical_nested_indeed}
+
+\def\chem_chemical_nested_indeed[#1][#2]%
+ {\clf_definechemical{\currentdefinedchemical}{#1}{\detokenize{#2}}}
+
+% chemical symbols
+
+\unexpanded\def\definechemicalsymbol
+ {\dodoubleempty\chem_symbol_define}
+
+\def\chem_symbol_define[#1][#2]%
+ {\setvalue{\??chemicalsymbol#1}{#2}}
+
+\unexpanded\def\chemicalsymbol[#1]%
+ {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname}
+
+\definechemicalsymbol[\s!unknown][] % \char"FFFD empty
+
+% size (small medium big)
+
+\edef\chemicaltoplocation{t}
+\edef\chemicalbotlocation{b}
+
+\unexpanded\def\chemicaltext#1%
+ {\mathematics
+ {\usechemicalstyleandcolor\c!style\c!color
+ \strut
+ \ifcase\currentxfontsize\or\scriptstyle\or\scriptscriptstyle\fi
+ #1}}
+
+\setvalue{\??chemicalsize\v!small }{\txx}
+\setvalue{\??chemicalsize\v!medium}{\tx}
+\setvalue{\??chemicalsize\v!big }{}
+
+\newtoks \everychemical
+\newtoks \everystructurechemical
+\newconditional\indisplaychemical
+
+\newtoks \t_chem_every_box
+\newbox \b_chem_result
+\newconditional\c_chem_some_text
+\newdimen \d_chem_width
+\newdimen \d_chem_height
+\newdimen \d_chem_depth
+
+\unexpanded\def\startchemical
+ {\dodoubleempty\chem_start}
+
+\def\chem_start[#1][#2]%
+ {\ifmmode\vcenter\else\vbox\fi % vpack ?
+ \bgroup
+ \synchronizestrut{\chemicalparameter\c!strut}%
+ \dontcomplain
+ \settrue\indisplaychemical
+ \forgetall
+ \ifsecondargument
+ \doifelseassignment{#1}
+ {\setupcurrentchemical[#1]}% same as \currentchemical
+ {\edef\currentchemical{#1}%
+ \setupcurrentchemical[#2]}%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\setupcurrentchemical[#1]}% same as \currentchemical
+ {\edef\currentchemical{#1}}%
+ \fi\fi
+ \the\everystructurechemical
+ \setbox\b_chem_result\hpack\bgroup
+ \clf_startchemical
+ width {\chemicalparameter\c!width}%
+ height {\chemicalparameter\c!height}%
+ left {\chemicalparameter\c!left}%
+ right {\chemicalparameter\c!right}%
+ top {\chemicalparameter\c!top}%
+ bottom {\chemicalparameter\c!bottom}%
+ scale {\chemicalparameter\c!scale}%
+ rotation {\chemicalparameter\c!rotation}%
+ symalign {\chemicalparameter\c!symalign}%
+ axis {\chemicalparameter\c!axis}% was \MPcolor{...}
+ framecolor {\chemicalparameter\c!framecolor}%
+ rulethickness {\number\dimexpr\chemicalparameter\c!rulethickness}%
+ offset {\number\dimexpr\chemicalparameter\c!offset}%
+ unit {\number\dimexpr\chemicalparameter\c!unit}%
+ factor {\number\chemicalparameter\c!factor}%
+ \relax
+ \startnointerference}
+
+\unexpanded\def\stopchemical
+ {\stopnointerference
+ \clf_stopchemical
+ \egroup
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+ \the\t_chem_every_box
+ \doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes
+ \egroup}
+
+\unexpanded\def\chem_framed_yes
+ {\localframedwithsettings
+ [\??chemicalframed]%
+ [\c!frame=\chemicalparameter\c!frame,
+ \c!rulethickness=\chemicalparameter\c!rulethickness,
+ \c!framecolor=\chemicalparameter\c!framecolor]%
+ {\vpack{\box\b_chem_result\vss}}} % remove depth
+
+\unexpanded\def\chem_framed_nop
+ {\directlocalframed
+ [\??chemicalframed]%
+ {\vpack{\box\b_chem_result\vss}}} % remove depth
+
+\let\startstructurechemical\startchemical
+\let\stopstructurechemical \stopchemical
+
+\unexpanded\def\structurechemical
+ {\dotripleempty\strc_chem_indeed}
+
+\appendtoks
+ \let\chemical\structurechemical
+\to\everystructurechemical
+
+\def\strc_chem_indeed
+ {\ifthirdargument
+ \expandafter\strc_chem_indeed_three
+ \else
+ \expandafter\strc_chem_indeed_two
+ \fi}
+
+\def\strc_chem_indeed_three[#1][#2][#3]%
+ {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored
+ \clf_chemicalcomponent
+ {#2}%
+ {\detokenize{#3}}%
+ {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points
+ {\chemicalparameter\c!rulecolor}%
+ \relax
+ \ignorespaces}
+
+\def\strc_chem_indeed_two[#1][#2]%
+ {\clf_chemicalcomponent
+ {#1}%
+ {\detokenize{#2}}%
+ {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points
+ {\chemicalparameter\c!rulecolor}%
+ \relax
+ \ignorespaces}
+
+\appendtoks
+ \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}%
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+\to \t_chem_every_box
+
+% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize)
+
+\appendtoks
+ \edef\chemicalbodyfont{\chemicalparameter\c!bodyfont}% public?
+ \ifx\chemicalbodyfont\empty
+ \switchtobodyfont[\chemicalbodyfont]%
+ \fi
+ \getvalue{\??chemicalsize\chemicalparameter\c!size}%
+% \to \everystructurechemical
+\to \everychemical
+
+\def\chemicaltoptext#1{\global\settrue\c_chem_some_text\gdef\m_chem_top_text{#1}\ignorespaces}
+\def\chemicalbottext#1{\global\settrue\c_chem_some_text\gdef\m_chem_bot_text{#1}\ignorespaces}
+\def\chemicalmidtext#1{\global\settrue\c_chem_some_text\gdef\m_chem_mid_text{#1}\ignorespaces}
+
+\appendtoks
+ \let\toptext\chemicaltoptext \glet\m_chem_top_text\empty
+ \let\bottext\chemicalbottext \glet\m_chem_bot_text\empty
+ \let\midtext\chemicalmidtext \glet\m_chem_mid_text\empty
+ \global\setfalse\c_chem_some_text
+\to \everystructurechemical
+
+\def\chem_add_texts
+ {\setbox2\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}%
+ \setbox4\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}%
+ \setbox6\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}%
+ \setbox\b_chem_result\hpack \bgroup
+ \box\b_chem_result
+ \hskip-\d_chem_width
+ \raise\d_chem_height\hpack{\lower\ht4\box4}%
+ \hskip-\d_chem_width
+ \lower.5\dimexpr\ht2-\dp2\relax\box2%
+ \hskip-\d_chem_width
+ \lower\d_chem_depth \hpack{\raise\dp6\box6}%
+ \hss
+ \egroup} % text on top of chemicals
+
+\appendtoks
+ \ifconditional\c_chem_some_text
+ \chem_add_texts
+ \d_chem_width \wd\b_chem_result
+ \d_chem_height\ht\b_chem_result
+ \d_chem_depth \dp\b_chem_result
+ \fi
+\to \t_chem_every_box
+
+% todo: enspace or emspace
+
+\definechemicalsymbol[space] [\enspace\quad\enspace]
+\definechemicalsymbol[plus] [\enspace+\enspace]
+\definechemicalsymbol[minus] [\enspace-\enspace]
+\definechemicalsymbol[gives] [\chem_arrow_construct\xrightarrow]
+\definechemicalsymbol[equilibrium] [\chem_arrow_construct\xrightoverleftarrow]
+\definechemicalsymbol[mesomeric] [\chem_arrow_construct\xleftrightarrow]
+\definechemicalsymbol[opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[SPACE] [{\chemicalsymbol[space]}]
+\definechemicalsymbol[PLUS] [{\chemicalsymbol[plus]}]
+\definechemicalsymbol[MINUS] [{\chemicalsymbol[minus]}]
+\definechemicalsymbol[GIVES] [{\chemicalsymbol[gives]}]
+\definechemicalsymbol[EQUILIBRIUM] [{\chemicalsymbol[equilibrium]}]
+\definechemicalsymbol[MESOMERIC] [{\chemicalsymbol[mesomeric]}]
+\definechemicalsymbol[OPENCOMPLEX] [{\chemicalsymbol[opencomplex]}]
+\definechemicalsymbol[CLOSECOMPLEX][{\chemicalsymbol[closecomplex]}]
+
+\def\chem_arrow_construct#1#2#3%
+ {\enspace
+ \mathematics{#1%
+ {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#3}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#2}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}%
+ \enspace}
+
+% special macros (probably needs some more work)
+
+\let\chem_box_normal_yes\hbox
+\let\chem_box_visual_yes\hbox
+\let\chem_box_visual_nop\relax
+
+\installtextracker
+ {chemistry.boxes}
+ {\let\chem_box_visual_yes\ruledhbox \let\chem_box_visual_nop\ruledhbox}
+ {\let\chem_box_visual_yes\hbox \let\chem_box_visual_nop\relax }
+
+\def\chem_top_construct#1#2#3#4%
+ {\hpack\bgroup
+ \setstrut
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\raise\dimexpr\dp\scratchboxone+\ht\scratchboxtwo\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \smashbox\scratchboxone
+ \box\scratchboxone
+ \box\scratchboxtwo
+ \egroup}
+
+\def\chem_bottom_construct#1#2#3#4%
+ {\hpack\bgroup
+ \setstrut
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\lower\dimexpr\dp\scratchboxtwo+\ht\scratchboxone\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \smashbox\scratchboxone
+ \box\scratchboxone
+ \box\scratchboxtwo
+ \egroup}
+
+\unexpanded\def\chemicalleft#1#2% redundant boxes thanks to visual
+ {\hbox\bgroup % hpack ?
+ \setstrut
+ \llap{\chem_box_visual_nop{\strut#1}}%
+ \chem_box_visual_nop{\strut#2}%
+ \egroup}
+
+\unexpanded\def\chemicalright#1#2% redundant boxes thanks to visual
+ {\hbox\bgroup % hpack ?
+ \setstrut
+ \chem_box_visual_yes{\strut#2}%
+ \rlap{\chem_box_visual_nop{\strut#1}}%
+ \egroup}
+
+\unexpanded\def\chemicaltop {\chem_top_construct \hss \hss }
+\unexpanded\def\chemicallefttop {\chem_top_construct \relax \hss }
+\unexpanded\def\chemicalrighttop {\chem_top_construct \hss \relax}
+\unexpanded\def\chemicalbottom {\chem_bottom_construct \hss \hss }
+\unexpanded\def\chemicalleftbottom {\chem_bottom_construct \relax \hss }
+\unexpanded\def\chemicalrightbottom {\chem_bottom_construct \hss \relax}
+
+\unexpanded\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}}
+\unexpanded\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}}
+\unexpanded\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}}
+\unexpanded\def\chemicalbottomright #1{\chemicalright{\chemicalleftbottom {#1}{}}}
+
+% \unexpanded\def\chemicalcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1\hss}}
+% \unexpanded\def\chemicalleftcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut #1\hss}}
+% \unexpanded\def\chemicalrightcentered#1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1}}
+
+% \let\chemicalsmashedmiddle\chemicalcentered
+% \let\chemicalsmashedleft \chemicalleftcentered
+% \let\chemicalsmashedright \chemicalrightcentered
+
+\unexpanded\def\chemicalalignedtext
+ {\ifmmode
+ \expandafter\chem_aligned_text_math
+ \else
+ \expandafter\chem_aligned_text_text
+ \fi}
+
+\let\chemicaltighttext\relax % maybe smaller strut
+
+\def\chem_aligned_text_text#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \usechemicalstyleandcolor\c!style\c!color
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
+ \setstrut\strut
+ #1\molecule{#3}#2%
+ \egroup
+ \endgroup}
+
+\def\chem_aligned_text_math#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
+ \setstrut\strut
+ #1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2%
+ \egroup
+ \endgroup}
+
+\unexpanded\def\chemicalcentered {\chemicalalignedtext\hss \hss }
+\unexpanded\def\chemicalleftcentered {\chemicalalignedtext\relax\hss }
+\unexpanded\def\chemicalrightcentered{\chemicalalignedtext\hss \relax}
+
+\let\chemicalsmashedmiddle\chemicalcentered
+\let\chemicalsmashedleft \chemicalleftcentered
+\let\chemicalsmashedright \chemicalrightcentered
+
+\unexpanded\def\chemicaloxidation#1#2#3%
+ {\chemicaltop{\txx\ifcase#2\relax0\else#1\convertnumber{I}{#2}\fi}{#3}}
+
+\unexpanded\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed!
+\unexpanded\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed!
+\unexpanded\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed!
+\unexpanded\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed!
+\unexpanded\def\chemicaloxidationone {\chemicaloxidation\relax1}
+\unexpanded\def\chemicaloxidationtwo {\chemicaloxidation\relax2}
+\unexpanded\def\chemicaloxidationthree{\chemicaloxidation\relax3}
+\unexpanded\def\chemicaloxidationfour {\chemicaloxidation\relax4}
+\unexpanded\def\chemicaloxidationfive {\chemicaloxidation\relax5}
+\unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6}
+\unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7}
+
+\unexpanded\def\chemicalbar
+ {\hpack \s!spread .5\emwidth \bgroup
+ \hss
+ \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight
+ \hss
+ \egroup}
+
+\appendtoks
+ \enforced\let |\chemicalbar % \SR{N|NH}
+ \enforced\let \+\chemicaloxidationplus
+ \enforced\let \-\chemicaloxidationminus
+ \enforced\let \[\chemicalforeveropen
+ \enforced\let \]\chemicalforeverclose
+ \enforced\let \1\chemicaloxidationone
+ \enforced\let \2\chemicaloxidationtwo
+ \enforced\let \3\chemicaloxidationthree
+ \enforced\let \4\chemicaloxidationfour
+ \enforced\let \5\chemicaloxidationfive
+ \enforced\let \6\chemicaloxidationsix
+ \enforced\let \7\chemicaloxidationseven
+ \enforced\let \X\chemicaltighttext
+ \enforced\let \T\chemicaltop
+ \enforced\let \B\chemicalbottom
+ \enforced\let \L\chemicalleft
+ \enforced\let\LC\chemicalleftcentered
+ \enforced\let \R\chemicalright
+ \enforced\let\RC\chemicalrightcentered
+ \enforced\let\TL\chemicaltopleft
+ \enforced\let\BL\chemicalbottomleft
+ \enforced\let\TR\chemicaltopright
+ \enforced\let\BR\chemicalbottomright
+ \enforced\let\LT\chemicallefttop
+ \enforced\let\LB\chemicalleftbottom
+ \enforced\let\RT\chemicalrighttop
+ \enforced\let\RB\chemicalrightbottom
+ \enforced\let\SL\chemicalsmashedleft
+ \enforced\let\SM\chemicalsmashedmiddle
+ \enforced\let\SR\chemicalsmashedright
+\to \everychemical
+
+% Should these also be defined in lower case, so as to be case independent?
+
+\appendtoks
+ \the\everychemical
+\to \everystructurechemical
+
+% inline
+
+% \unexpanded\def\chemical
+% {\ifinformula
+% \expandafter\displaychemical
+% \else
+% \expandafter\inlinechemical
+% \fi}
+
+\unexpanded\def\chemical
+ {\ifinformula
+ \expandafter\indisplaychemical
+ \else
+ \expandafter\inlinechemical
+ \fi}
+
+\unexpanded\def\indisplaychemical
+ {\mathstylecommand\displaychemical\inlinechemical\inlinechemical}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\clf_inlinechemical{#1}}}%
+ \endgroup}
+
+\unexpanded\def\displaychemical
+ {\dotriplegroupempty\chem_display}
+
+\def\chem_display#1#2#3%
+ {\the\everychemical
+ \everychemical\emptytoks
+ \quad
+ \vcenter\bgroup
+ \usechemicalstyleandcolor\c!style\c!color
+ \ifthirdargument
+ \ifsecondargument
+ \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
+ \else
+ \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}%
+ \fi
+ \else
+ \hbox{\molecule{#1}}%
+ \fi
+ \egroup
+ \quad}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}}
+
+\unexpanded\def\chemicalbondrule
+ {\hpack{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
+
+\definechemicalsymbol[i:space] [\enspace\quad\enspace]
+\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace]
+\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace]
+\definechemicalsymbol[i:equals] [\enspace\mathematics{=}\enspace]
+\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace]
+\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:single] [\chemicalbondrule]
+\definechemicalsymbol[i:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+
+\unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]}
+\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:triple]}
+\unexpanded\def\chemicalgives {\chemicalsymbol[i:gives]}
+\unexpanded\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]}
+\unexpanded\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]}
+\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]}
+\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]}
+\unexpanded\def\chemicalequals {\chemicalsymbol[i:equals]}
+\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]}
+\unexpanded\def\chemicalinline #1{#1}
+
+% display
+
+\newconditional\c_chem_has_top
+\newconditional\c_chem_has_bot
+
+\newtoks\t_chem_top
+\newtoks\t_chem_mid
+\newtoks\t_chem_bot
+
+\newif\ifinchemicalformula
+
+\unexpanded\def\startchemicalformula
+ {\mathortext\vcenter\vbox\bgroup
+ \forgetall
+ \inchemicalformulatrue
+ \the\everychemical
+ \everychemical\emptytoks
+ \t_chem_top\emptytoks % not needed
+ \t_chem_mid\emptytoks % not needed
+ \t_chem_bot\emptytoks % not needed
+ \let\chemical\formulachemical
+ \setfalse\c_chem_has_top
+ \setfalse\c_chem_has_bot}
+
+\unexpanded\def\stopchemicalformula
+ {\tabskip\emwidth\relax
+ \nointerlineskip
+ \ifconditional\c_chem_has_top
+ \ifconditional\c_chem_has_bot
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \else
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
+ \fi
+ \else
+ \ifconditional\c_chem_has_bot
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \else
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr}%
+ \fi
+ \fi
+ \egroup}
+
+% for the moment we have a special set
+
+\definechemicalsymbol[d:space] [\enspace\quad\enspace]
+\definechemicalsymbol[d:plus] [\enspace+\enspace]
+\definechemicalsymbol[d:minus] [\enspace-\enspace]
+\definechemicalsymbol[d:equals] [\enspace=\enspace]
+\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow
+\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow
+\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow
+\definechemicalsymbol[d:single] [\chemicalbondrule]
+\definechemicalsymbol[d:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[d:SPACE] [{\chemicalsymbol[d:space]}]
+\definechemicalsymbol[d:PLUS] [{\chemicalsymbol[d:plus]}]
+\definechemicalsymbol[d:MINUS] [{\chemicalsymbol[d:minus]}]
+\definechemicalsymbol[d:EQUALS] [{\chemicalsymbol[d:equals]}]
+\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}]
+\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}]
+\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}]
+\definechemicalsymbol[d:SINGLE] [{\chemicalsymbol[d:single]}]
+\definechemicalsymbol[d:DOUBLE] [{\chemicalsymbol[d:double]}]
+\definechemicalsymbol[d:TRIPLE] [{\chemicalsymbol[d:triple]}]
+\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}]
+\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}]
+
+\unexpanded\def\formulachemical
+ {\relax\dotriplegroupempty\chem_formula}
+
+\def\chem_formula#1#2#3% we could do hboxes and measure
+ {\ifthirdargument
+ \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
+ \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
+ \else\ifsecondargument
+ \chem_formula_top_nop
+ \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
+ \else
+ \chem_formula_top_nop
+ \chem_formula_bot_nop
+ \fi\fi
+ \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname
+ \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}%
+ \else
+ \toksapp\t_chem_mid{\molecule{#1}\aligntab}%
+ \fi}
+
+\def\chem_formula_mid#1%
+ {\csname\??chemicalsymbol\detokenize{#1}\endcsname}
+
+\def\chem_formula_top_nop {\toksapp\t_chem_top{\aligntab}}
+\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}}
+\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top}
+\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot}
+
+\def\chem_formula_top_indeed#1{\strut#1}
+\def\chem_formula_bot_indeed#1{\strut#1}
+
+% Experimental: defaults might change.
+
+\definefloat
+ [\v!chemical]
+ [\v!chemicals]
+
+\setuplabeltext
+ [\v!chemical=]
+
+\setupfloat
+ [\v!chemical]
+ [\c!location=\v!here,
+ \c!inner=\hsize.8\textwidth\dontleavehmode, % brr
+ \c!align={\v!flushleft,\v!lohi}]
+
+\setupcaption
+ [\v!chemical]
+ [\c!location=\v!right,
+ \c!distance=\zeropoint,
+ \c!width=.2\textwidth,
+ \c!align=\v!flushright]
+
+% Can be used as for displayed math: \startplaceformula... to display a chemical formula
+% or a chemical structure:
+%
+% \startplacechemical
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+% \stopplacechemical
+
+% gone: state option resolution offset (now frame offset) alternative
+
+\setupchemicalframed
+ [\c!align=\v!normal,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\definecolor % private color
+ [chemicalframecolor]
+ [r=.75,g=.85,b=.95]
+
+\setupchemical
+ [\c!frame=,
+ \c!width=\v!fit, % or unitless number, multiplies scale*unit
+ \c!height=\v!fit, % or unitless number, multiplies scale*unit
+ \c!left=\v!fit, % or unitless number, multiplies scale*unit
+ \c!right=\v!fit, % or unitless number, multiplies scale*unit
+ \c!top=\v!fit, % or unitless number, multiplies scale*unit
+ \c!bottom=\v!fit, % or unitless number, multiplies scale*unit
+ \c!bodyfont=,
+ \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies unit)
+ \c!size=\v!medium,
+ \c!textsize=\v!big, % how is textsize used??
+ \c!axis=\v!off,
+ \c!style=\rm,
+ \c!rotation=0, % unitless number (interpreted as degrees)
+ \c!symalign=\v!auto,
+ \c!location=, % not yet used (was interaction related in mkii)
+ \c!offset=.25\emwidth,
+ \c!unit=\emwidth,
+ \c!factor=3,
+ \c!color=,
+ \c!strut=\v!yes,
+ \c!framecolor=chemicalframecolor,
+ \c!rulethickness=0.6pt, %1.5\linewidth,
+ \c!rulecolor=]
+
+%D Compatibility:
+
+\definechemical[+R] {\chemical[RR]}
+\definechemical[-R] {\chemical[LR]}
+
+\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]}
+\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]}
+
+\definechemical[NEWMAN] {\chemical[]}
+\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]}
+\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]}
+\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]}
+\definechemical[SIX:FRONT] {\chemical[SIXFRONT]}
+\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 24092d852..77391580f 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -97,7 +97,6 @@ local tex = tex
local texsprint = tex.sprint -- just appended (no space,eol treatment)
local texprint = tex.print -- each arg a separate line (not last in directlua)
----- texwrite = tex.write -- all 'space' and 'character'
-local texgetcount = tex.getcount
local isnode = node.is_node
local writenode = node.write
@@ -114,6 +113,15 @@ local isprintable = tex.isprintable or function(n)
return n and (type(n) == "string" or isnode(n) or istoken(n))
end
+if tex.runlocal then
+ -- obselete names
+ tex.runtoks = tex.runlocal
+ tex.quittoks = tex.quitlocal
+else
+ tex.runlocal = tex.runtoks
+ tex.quitlocal = tex.quittoks
+end
+
local catcodenumbers = catcodes.numbers
local ctxcatcodes = catcodenumbers.ctxcatcodes
@@ -133,13 +141,15 @@ local report_cld = logs.reporter("cld","stack")
local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end)
-local trialtypesettingstate = createtoken("trialtypesettingstate").index
+local trialtypesetting = function() return false end
-function context.trialtypesetting()
- return texgetcount(trialtypesettingstate) ~= 0
- -- return texgetcount("trialtypesettingstate") ~= 0
+function context.settrialtypesettingmethod(f)
+ trialtypesetting = f
+ context.trialtypesetting = f
end
+context.trialtypesetting = function() return trialtypesetting() end -- can be aliased !
+
local knownfunctions = (lua.getfunctionstable or lua.get_functions_table)(true)
local showstackusage = false
@@ -154,14 +164,12 @@ local usedstack = function()
end
local flushfunction = function(slot,arg)
- if arg() then
+ if arg() or trialtypesetting() then
-- keep
- elseif texgetcount(trialtypesettingstate) == 0 then
+ else
noffreed = noffreed + 1
freed[noffreed] = slot
knownfunctions[slot] = false
- else
- -- keep
end
end
@@ -181,13 +189,13 @@ local storefunction = function(arg)
end
local flushnode = function(slot,arg)
- if texgetcount(trialtypesettingstate) == 0 then
+ if trialtypesetting() then
+ writenode(copynodelist(arg))
+ else
writenode(arg)
noffreed = noffreed + 1
freed[noffreed] = slot
knownfunctions[slot] = false
- else
- writenode(copynodelist(arg))
end
end
@@ -378,15 +386,61 @@ interfaces.namesofscanners = namesofscanners
storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners")
-local function registerscanner(name,action,protected,public,usage) -- todo: combine value and condition
- rawset(interfacescanners,name,action)
- local n = storedscanners[name]
- n = registerfunction("interfaces.scanners."..name,true,n)
- storedscanners[name] = n
- namesofscanners[n] = name
- name = public and name or (privatenamespace .. name)
- -- print(">>",name,protected and "protected" or "",usage or "macro")
- setluatoken(name,n,"global",protected and "protected" or "",usage or "macro")
+-- local function registerscanner(name,action,protected,public,usage) -- todo: combine value and condition
+-- rawset(interfacescanners,name,action)
+-- local n = storedscanners[name]
+-- n = registerfunction("interfaces.scanners."..name,true,n)
+-- storedscanners[name] = n
+-- namesofscanners[n] = name
+-- name = public and name or (privatenamespace .. name)
+-- -- print(">>",name,protected and "protected" or "",usage or "macro")
+-- setluatoken(name,n,"global",protected and "protected" or "",usage or "macro")
+-- end
+
+-- todo: bitmap
+
+local registerscanner if CONTEXTLMTXMODE > 0 then
+
+ -- always permanent but we can consider to obey permanent==false
+
+ local function toflags(specification)
+ local protected = specification.protected and "protected" -- or ""
+ local usage = specification.usage
+ if usage == "value" then
+ return "global", "value", "permanent", protected
+ elseif usage == "condition" then
+ return "global", "conditional", "permanent", protected
+ elseif specification.frozen then
+ return "global", "frozen", protected
+ elseif specification.permanent == false or specification.onlyonce then -- for now onlyonce here
+ return "global", protected
+ else
+ return "global", "permanent", protected
+ end
+ end
+
+
+ registerscanner = function(name,action,specification)
+ rawset(interfacescanners,name,action)
+ local n = registerfunction("interfaces.scanners."..name,true,storedscanners[name])
+ storedscanners[name] = n
+ namesofscanners[n] = name
+ name = specification.public and name or (privatenamespace .. name)
+ setluatoken(name,n,toflags(specification))
+ end
+
+else
+
+ registerscanner = function(name,action,specification)
+ rawset(interfacescanners,name,action)
+ local n = storedscanners[name]
+ n = registerfunction("interfaces.scanners."..name,true,n)
+ storedscanners[name] = n
+ namesofscanners[n] = name
+ name = specification.public and name or (privatenamespace .. name)
+ setluatoken(name,n,"global",specification.protected and "protected" or "")
+ end
+
end
interfaces.registerscanner = registerscanner
@@ -696,7 +750,7 @@ end
local containseol = patterns.containseol
-local lua_expandable_call_code = tokens.commands.lua_expandable_call
+local lua_call_code = tokens.commands.lua_expandable_call or tokens.commands.lua_call
local sortedhashindeed = false
@@ -793,7 +847,7 @@ local function writer(parent,command,...) -- already optimized before call
local tj = ti[1]
if type(tj) == "function" then
tj = storefunction(tj)
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),"]")
+ flush(currentcatcodes,"[",newtoken(tj,lua_call_code),"]")
else
flush(currentcatcodes,"[",tj,"]")
end
@@ -803,7 +857,7 @@ local function writer(parent,command,...) -- already optimized before call
local tj = ti[j]
if type(tj) == "function" then
tj = storefunction(tj)
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),j == tn and "]" or ",")
+ flush(currentcatcodes,"[",newtoken(tj,lua_call_code),j == tn and "]" or ",")
else
if j == tn then
flush(currentcatcodes,tj,"]")
@@ -816,7 +870,7 @@ local function writer(parent,command,...) -- already optimized before call
elseif typ == "function" then
-- todo: ctx|prt|texcatcodes
ti = storefunction(ti)
- flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_code),"}")
+ flush(currentcatcodes,"{",newtoken(ti,lua_call_code),"}")
elseif typ == "boolean" then
if ti then
flushdirect(currentcatcodes,"\r")
@@ -972,7 +1026,7 @@ local caller = function(parent,f,a,...)
elseif typ == "function" then
-- ignored: a ...
f = storefunction(f)
- flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_code),"}")
+ flush(currentcatcodes,"{",newtoken(f,lua_call_code),"}")
elseif typ == "boolean" then
if f then
if a ~= nil then
@@ -1083,6 +1137,14 @@ statistics.register("traced context", function()
end
end)
+-- The cmd names were synchronized with the normal call cmd names.
+
+local luacalls = { -- luatex luametatex
+ lua_expandable_call = true, -- normal
+ lua_call = true, -- protected normal
+ lua_protected_call = true, -- protected
+}
+
local function userdata(argument)
if isnode(argument) then
return formatters["<< %s node %i>>"](nodes.nodecodes[argument.id],tonut(argument))
@@ -1092,8 +1154,7 @@ local function userdata(argument)
-- return formatters["<<\\%s>>"](csname)
return formatters["\\%s"](csname)
end
- local cmdname = argument.cmdname
- if cmdname == "lua_expandable_call" or cmdname == "lua_call" then
+ if luacall[argument.cmdname] then
return "<<function>>" -- argument.mode
end
return "<<token>>"
@@ -1735,8 +1796,10 @@ do
if CONTEXTLMTXMODE > 0 then
- local prefixcodes = tex.getprefixvalues()
- tex.prefixcodes = table.swapped(prefixcodes,prefixcodes) -- utilities.storage.allocate()
+ -- also elsewhere
+
+ local flagcodes = tex.getflagvalues()
+ tex.flagcodes = table.swapped(flagcodes,flagcodes) -- utilities.storage.allocate()
end
diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv
index 0ec2d408b..70c9c12e3 100644
--- a/tex/context/base/mkiv/cldf-ini.mkiv
+++ b/tex/context/base/mkiv/cldf-ini.mkiv
@@ -1,8 +1,8 @@
%D \module
-%D [ file=cldf-ini,
-%D version=2010.10.19,,
-%D title=\CONTEXT\ \LUA\ Document Functions,
-%D subtitle=Initialization,
+%D [ file=cldf-int,
+%D version=2019.01.01,
+%D title=\CONTEXT\ Data Macros,
+%D subtitle=Integer,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
diff --git a/tex/context/base/mkiv/cldf-int.mkxl b/tex/context/base/mkiv/cldf-int.mkxl
index 603c22afc..a564afc80 100644
--- a/tex/context/base/mkiv/cldf-int.mkxl
+++ b/tex/context/base/mkiv/cldf-int.mkxl
@@ -1,8 +1,8 @@
%D \module
-%D [ file=mult-ini,
-%D version=2008.10.22, % 1996.06.01,
-%D title=\CONTEXT\ Multilingual Macros,
-%D subtitle=Initialization,
+%D [ file=cldf-int,
+%D version=2019.01.01,
+%D title=\CONTEXT\ Data Macros,
+%D subtitle=Integer,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -15,17 +15,20 @@
\registerctxluafile{cldf-int}{autosuffix}
+%D These are user commands so we don't add any protection against overloading
+%D here.
+
\unprotect
-\unexpanded\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}}
-\unexpanded\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}}
+\permanent\protected\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}}
+\permanent\protected\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}}
\installcorenamespace{datavalue}
-\unexpanded\def\setdatavalue#1#2% #2 is a number (expression)
- {\expandafter\letdatacode\csname\??datavalue#1\endcsname\numexpr#2\relax}
+\permanent\protected\def\setdatavalue#1#2% #2 is a number (expression)
+ {\expandafter\integerdef\csname\??datavalue#1\endcsname\numexpr#2\relax}
-\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname}
-\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname}
+\permanent\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname}
+\permanent\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname}
\protect \endinput
diff --git a/tex/context/base/mkiv/cldf-lmt.lmt b/tex/context/base/mkiv/cldf-lmt.lmt
index 9889131a5..f3121eadc 100644
--- a/tex/context/base/mkiv/cldf-lmt.lmt
+++ b/tex/context/base/mkiv/cldf-lmt.lmt
@@ -57,7 +57,7 @@ local skip_code = values.skip
local boolean_code = values.boolean
local float_code = values.float
-local global_code = tex.prefixcodes.global
+local global_code = tex.flagcodes.global
local context = context
@@ -428,8 +428,8 @@ local slots = { }
local nofslots = 0
local nofgrouped = 0
-local getdata = tokens.getdata
-local setdata = tokens.setdata
+local getinteger = tokens.getinteger
+local setinteger = tokens.setinteger
local report = logs.reporter("lua table")
@@ -448,7 +448,7 @@ local function newluatable(name,mt,dispose)
t = nofgrouped
end
if mt then
- mt = getdata(name)
+ mt = getinteger(name)
if mt then
mt = grouped[mt]
if mt then
@@ -457,7 +457,7 @@ local function newluatable(name,mt,dispose)
end
end
grouped[t] = g
- setdata(name,t)
+ setinteger(name,t)
-- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll
-- think of something that we can set it at the Lua end.
if dispose then
@@ -466,7 +466,7 @@ local function newluatable(name,mt,dispose)
end
local function disposeluatable(name)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g then
grouped[t] = false
@@ -476,7 +476,7 @@ local function disposeluatable(name)
end
local function setluatable(name,kv)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g and kv then
for k, v in next, kv do
@@ -486,7 +486,7 @@ local function setluatable(name,kv)
end
local function getfromluatable(name,k)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g then
local v = g[k]
@@ -505,7 +505,7 @@ local function getfromluatable(name,k)
end
local function idxfromluatable(name,k)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g then
local v = g[k]
@@ -516,7 +516,7 @@ local function idxfromluatable(name,k)
end
local function getluatable(name,k)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g then
return g
@@ -524,7 +524,7 @@ local function getluatable(name,k)
end
local function inspectluatable(name)
- local t = getdata(name)
+ local t = getinteger(name)
local g = grouped[t]
if g then
report("%s", serialize(g,'[grouped slot ' .. t .. ']'))
diff --git a/tex/context/base/mkiv/cldf-scn.lua b/tex/context/base/mkiv/cldf-scn.lua
index fa7ff042c..84b2957ab 100644
--- a/tex/context/base/mkiv/cldf-scn.lua
+++ b/tex/context/base/mkiv/cldf-scn.lua
@@ -77,7 +77,8 @@ function interfaces.implement(specification)
if knownscanner(name) and not specification.overload then
report("warning: interface scanner %a is overloaded",name)
end
- register(name,scanner,specification.protected,specification.public,specification.usage)
+ -- register(name,scanner,specification.protected,specification.public,specification.usage)
+ register(name,scanner,specification)
if private then
return
end
diff --git a/tex/context/base/mkiv/colo-ini.mkiv b/tex/context/base/mkiv/colo-ini.mkiv
index 46931d886..7faaa5c5a 100644
--- a/tex/context/base/mkiv/colo-ini.mkiv
+++ b/tex/context/base/mkiv/colo-ini.mkiv
@@ -1107,9 +1107,8 @@
%D \stopregistercolor
%D \stoptyping
-\let\maintextcolor \empty
-\def\defaulttextcolor {black}
-\def\s!themaintextcolor{themaintextcolor}
+\let\maintextcolor \empty
+\def\defaulttextcolor{black}
\unexpanded\def\inheritmaintextcolor
{\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}
diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl
index 72ee3db32..e8ea71b8d 100644
--- a/tex/context/base/mkiv/colo-ini.mkxl
+++ b/tex/context/base/mkiv/colo-ini.mkxl
@@ -11,9 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D We need to clean this up further but first we have to make sure that mkiv
-%D code works ok.
-
\writestatus{loading}{ConTeXt Color Macros / Initialization}
%D Todo: move color space in color attribute (last two bits)
@@ -98,16 +95,7 @@
%D \stopcombination
%D \stoptyping
-\unexpanded\def\definecolor {\dodoubleargument\colo_basics_define}
-\unexpanded\def\defineglobalcolor {\dodoubleargument\colo_basics_define_global}
-\unexpanded\def\defineprocesscolor {\dotripleargument\colo_basics_define_process}
-\unexpanded\def\definenamedcolor {\dodoubleargument\colo_basics_define_named}
-\unexpanded\def\definespotcolor {\dotripleargument\colo_basics_define_spot}
-\unexpanded\def\definemultitonecolor {\doquadrupleempty\colo_basics_define_multitone}
-\unexpanded\def\definetransparency {\dodoubleargument\colo_basics_define_transpancy}
-\unexpanded\def\defineglobaltransparency{\dodoubleargument\colo_basics_define_transpancy_global}
-
-\unexpanded\def\loadfoundcolorsetfile#1#2% name foundname / not a user command
+\permanent\protected\def\loadfoundcolorsetfile#1#2% name foundname / not a user command
{\startreadingfile
\startcolorset[#1]%
\input{#2}%
@@ -135,11 +123,11 @@
\let\g_color\empty
\let\g_style\empty
-\unexpanded\def\switchtocolor[#1]{\begincsname#1\endcsname}
+\protected\def\switchtocolor[#1]{\begincsname#1\endcsname}
% transparency
-\unexpanded\def\transparent[#1]%
+\permanent\protected\def\transparent[#1]%
{\bgroup
\edef\currenttransparencyname{#1}%
% the \relax catches a non existent csname
@@ -150,7 +138,7 @@
\fi
\let\nexttoken}
-\unexpanded\def\starttransparent[#1]%$
+\permanent\protected\def\starttransparent[#1]%$
{\begingroup
\edef\currenttransparencyname{#1}%
\ifx\currenttransparencyname\v!reset
@@ -159,12 +147,12 @@
\begincsname\??transparencysetter\currenttransparencyname\endcsname\relax
\fi}
-\unexpanded\def\stoptransparent
+\permanent\protected\def\stoptransparent
{\endgroup}
% color
-\unexpanded\def\coloronly[#1]%
+\permanent\protected\def\coloronly[#1]%
{\bgroup
\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
@@ -174,7 +162,7 @@
\fi
\let\nexttoken}
-\unexpanded\def\startcoloronly[#1]%$
+\permanent\protected\def\startcoloronly[#1]%$
{\begingroup
\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
@@ -183,12 +171,12 @@
\colo_helpers_activate_yes_only
\fi}
-\unexpanded\def\stopcoloronly
+\permanent\protected\def\stopcoloronly
{\endgroup}
% color + transparency
-\unexpanded\def\color[#1]%
+\permanent\protected\def\color[#1]%
{\bgroup
\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
@@ -198,12 +186,12 @@
\fi
\let\nexttoken}
-\unexpanded\def\graycolor[#1]%
+\permanent\protected\def\graycolor[#1]%
{\bgroup
\colo_helpers_set_model\s!gray\colo_helpers_activate{#1}%
\let\nexttoken}
-\unexpanded\def\startcolor[#1]%$
+\permanent\protected\def\startcolor[#1]%$
{\begingroup
\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
@@ -212,24 +200,24 @@
\colo_helpers_activate_yes
\fi}
-\unexpanded\def\stopcolor
+\permanent\protected\def\stopcolor
{\endgroup}
-\unexpanded\def\colored[#1]%
+\permanent\protected\def\colored[#1]%
{\bgroup
\colo_basics_defined_and_activated{#1}%
\let\nexttoken}
-\unexpanded\def\fastcolored[#1]#2%
+\permanent\protected\def\fastcolored[#1]#2%
{\begingroup % is this command still needed?
\colo_basics_defined_and_activated{#1}%
#2%
\endgroup}
-\unexpanded\def\directcolored[#1]%
+\permanent\protected\def\directcolored[#1]%
{\colo_basics_defined_and_activated{#1}}
-\unexpanded\def\fastcolor[#1]#2%
+\permanent\protected\def\fastcolor[#1]#2%
{\begingroup % is this command still needed?
\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
@@ -240,7 +228,7 @@
#2%
\endgroup}
-\unexpanded\def\directcolor[#1]%
+\permanent\protected\def\directcolor[#1]%
{\edef\currentcolorname{#1}%
\ifempty\currentcolorprefix
\colo_helpers_activate_nop
@@ -250,10 +238,10 @@
%D The following command is obsolete:
-\unexpanded\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]}
-\unexpanded\def\stopcolorpage {\stopcolor}
+\permanent\protected\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]}
+\permanent\protected\def\stopcolorpage {\stopcolor}
-\unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
+\permanent\protected\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
{\begingroup
\colo_helpers_activate{#1}%
\normalexpanded{\endgroup\edef\noexpand#2%
@@ -264,8 +252,8 @@
%D \macros
%D {startcurrentcolor,stopcurrentcolor}
-\unexpanded\def\startcurrentcolor{\startcolor[\outercolorname]}
-\unexpanded\def\stopcurrentcolor {\stopcolor}
+\permanent\protected\def\startcurrentcolor{\startcolor[\outercolorname]}
+\permanent\protected\def\stopcurrentcolor {\stopcolor}
%D \macros
%D {setupcolor}
@@ -290,9 +278,9 @@
%D \usecolors[dem]
%D \stoptyping
-\unexpanded\def\startcolorset[#1]{\clf_startcolorset{#1}}
-\unexpanded\def\stopcolorset {\clf_stopcolorset}
-\unexpanded\def\usecolors [#1]{\clf_usecolors{#1}}
+\permanent\protected\def\startcolorset[#1]{\clf_startcolorset{#1}}
+\permanent\protected\def\stopcolorset {\clf_stopcolorset}
+\permanent\protected\def\usecolors [#1]{\clf_usecolors{#1}}
\let\setupcolor\usecolors
@@ -351,7 +339,7 @@
\newcount\c_colo_nesting
-\unexpanded\def\pushcolor[#1]%
+\permanent\protected\def\pushcolor[#1]%
{\global\advance\c_colo_nesting\plusone
\expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname
{\c_attr_colormodel \the\c_attr_colormodel
@@ -360,7 +348,7 @@
\relax}% stack
\colo_helpers_activate{#1}}
-\unexpanded\def\popcolor
+\permanent\protected\def\popcolor
{\csname\??colorstack\number\c_colo_nesting\endcsname
\global\advance\c_colo_nesting\minusone}
@@ -369,11 +357,11 @@
\newcount\c_colo_saved_attribute_color
\newcount\c_colo_saved_attribute_transparency
-\unexpanded\def\savecolor
+\permanent\protected\def\savecolor
{\c_colo_saved_attribute_color \c_attr_color
\c_colo_saved_attribute_transparency\c_attr_transparency}
-\unexpanded\def\restorecolor
+\permanent\protected\def\restorecolor
{\c_attr_color \c_colo_saved_attribute_color
\c_attr_transparency\c_colo_saved_attribute_transparency}
@@ -443,8 +431,10 @@
\let\c_colo_palet\relax
\def\colo_palet_allocate#1%
- {\expandafter\let \csname\??paletlist#1\endcsname\empty
- \expandafter\newcount\csname\??paletsize#1\endcsname}
+ {\expandafter\let\csname\??paletlist#1\endcsname\empty
+ \ifcsname\??paletsize#1\endcsname\else
+ \expandafter\newcount\csname\??paletsize#1\endcsname
+ \fi}
\def\colo_palet_prepare#1%
{\edef\colo_palet_name{#1}%
@@ -453,15 +443,16 @@
\else
\colo_palet_allocate\colo_palet_name
\fi
- \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}%
- \expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname}
+ \enforced\expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname
+ \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}}
\def\colo_palet_extend#1%
{\addtocommalist{#1}\m_colo_palet
\expandafter\let\csname\??paletlist\colo_palet_name\endcsname\m_colo_palet
+ %\advance\csname\??paletsize\colo_palet_name\endcsname\plusone
\advance\c_colo_palet\plusone}
-\unexpanded\def\doifelsecolorpalet#1%
+\permanent\protected\def\doifelsecolorpalet#1%
{\ifcsname\??paletlist#1\endcsname
\expandafter\firstoftwoarguments
\else
@@ -471,41 +462,75 @@
\let\paletlist\empty
\let\paletsize\!!zerocount
-\unexpanded\def\getpaletlist[#1]%
+\permanent\protected\def\getpaletlist[#1]%
{\edef\paletlist{\begincsname\??paletlist#1\endcsname}}
-\unexpanded\def\getpaletsize[#1]%
+\permanent\protected\def\getpaletsize[#1]%
{\ifcsname\??paletsize#1\endcsname
\edef\paletsize{\the\lastnamedcs}%
\else
\let\paletsize\!!zerocount
\fi}
-\unexpanded\def\definepalet
- {\dotripleempty\colo_palets_define}
-
-\def\colo_palets_define
- {\ifthirdargument
- \expandafter\colo_palets_define_b
- \else
+%% \protected\def\definepalet
+%% {\dotripleempty\colo_palets_define}
+%%
+%% \def\colo_palets_define
+%% {\ifthirdargument
+%% \expandafter\colo_palets_define_b
+%% \else
+%% \expandafter\colo_palets_define_a
+%% \fi}
+%%
+%% \protected\def\colo_palets_define_a[#1][#2][#3]%
+%% \protected\def\colo_palets_define_b[#1][#2][#3]%
+
+\permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ \expandafter\gobblethreearguments
+ \or
+ \expandafter\gobblethreearguments
+ \or
\expandafter\colo_palets_define_a
- \fi}
+ \or
+ \expandafter\colo_palets_define_b
+ \fi{#1}{#2}{#3}}
-\unexpanded\def\colo_palets_define_a[#1][#2][#3]%
+\protected\def\colo_palets_define_a#1#2#3%
{\colo_palet_prepare{#1}%
\ifcondition\validassignment{#2}%
\setevalue{\??colorpaletspecification#1}{#2}%
\processcommalist[#2]{\colo_palets_define_one{#1}}%
\orelse\ifcsname\??colorpaletspecification#2\endcsname
- \normalexpanded{\colo_palets_define[#1][\lastnamedcs]}%
+ \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}\empty}%
\fi}
-\unexpanded\def\colo_palets_define_b[#1][#2][#3]%
+\protected\def\colo_palets_define_b#1#2#3%
{\colo_palet_prepare{#1}%
\setevalue{\??colorpaletspecification#1}{#2}%
\colo_palet_extend{#2}%
\colo_palets_define_assign{#1}{#2}{#3}}
+% % or, it being not that critital, just this
+%
+% \permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]%
+% {\ifarguments
+% \or
+% \or
+% \colo_palet_prepare{#1}%
+% \ifcondition\validassignment{#2}%
+% \setevalue{\??colorpaletspecification#1}{#2}%
+% \processcommalist[#2]{\colo_palets_define_one{#1}}%
+% \orelse\ifcsname\??colorpaletspecification#2\endcsname
+% \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}{}}%
+% \fi
+% \or
+% \colo_palet_prepare{#1}%
+% \setevalue{\??colorpaletspecification#1}{#2}%
+% \colo_palet_extend{#2}%
+% \colo_palets_define_assign{#1}{#2}{#3}%
+% \fi}
+
\def\colo_palets_define_one#1#2% get rid of { }
{\ifcondition\validassignment{#2}% catch empty entries
\colo_palets_define_two{#1}[#2]%
@@ -539,12 +564,9 @@
\newtoks\everysetuppalet
-\unexpanded\def\setuppalet
- {\dosingleempty\colo_palets_setup}
-
% \newtoks\t_colo_prefix % used in mp interface
-\def\colo_palets_setup[#1]%
+\permanent\tolerant\protected\def\setuppalet[#1]%
{\edef\currentcolorpalet{#1}%
\ifempty\currentcolorpalet
% seems to be a reset
@@ -631,10 +653,10 @@
%D
%D These speak for themselves. See \type {colo-ext} for usage.
-\unexpanded\def\negatecolorcomponent#1% #1 = \macro
+\permanent\protected\def\negatecolorcomponent#1% #1 = \macro
{\edef#1{\clf_negatecolorcomponent{#1}}}
-\def\negatedcolorcomponent#1%
+\permanent\def\negatedcolorcomponent#1%
{\clf_negatecolorcomponent{#1}}
%D \macros
@@ -670,7 +692,7 @@
% draw btex test etex withprescript \mptexcolor{blue} ;
% \stopMPpage
-\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
+\permanent\protected\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
{\colo_helpers_set_model{#1}} % only for local usage
\def\colo_helpers_set_model#1% direct
@@ -790,12 +812,12 @@
\let\dousecolorparameter\colo_helpers_activate
-\unexpanded\def\dousecolorhashparameter#1#2%
+\permanent\protected\def\dousecolorhashparameter#1#2%
{\ifcsname#1#2\endcsname
\expandafter\dousecolorparameter\csname#1#2\endcsname
\fi}
-\unexpanded\def\dousecurrentcolorparameter
+\permanent\protected\def\dousecurrentcolorparameter
{\let\currentcolorname\currentcolorparameter % maybe only when success
\ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
\lastnamedcs
@@ -807,7 +829,7 @@
\let\dosetcolorattribute\dousecolorhashparameter % for a while
-\unexpanded\def\deactivatecolor % sort of public but a bad name
+\permanent\protected\def\deactivatecolor % sort of public but a bad name
{\let\currentcolorname\s!black
\c_attr_color \attributeunsetvalue
\c_attr_transparency\attributeunsetvalue}
@@ -833,99 +855,78 @@
\newcount\c_colo_protection
-\unexpanded\def\startprotectedcolors
- {\advance\c_colo_protection\plusone}
-
-\unexpanded\def\stopprotectedcolors
- {\advance\c_colo_protection\minusone}
+\permanent\protected\def\startprotectedcolors{\advance\c_colo_protection\plusone }
+\permanent\protected\def\stopprotectedcolors {\advance\c_colo_protection\minusone}
-\def\colo_basics_define[#1][#2]%
-% {\edef\m_colo_old{#1}%
-% \edef\m_colo_new{#2}%
-% \ifx\m_colo_old\m_colo_new
+\permanent\tolerant\protected\def\definecolor[#1]#*[#2]%
{\iftok{#1}{#2}%
% maybe a warning
\else
\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
\colo_basics_synchronize{#1}%
\ifcase\c_colo_protection
- \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \protected\setvalue{#1}{\colo_helpers_activate{#1}}%
\fi
\fi}
-\def\colo_basics_define_global[#1][#2]%
-% {\edef\m_colo_old{#1}%
-% \edef\m_colo_new{#2}%
-% \ifx\m_colo_old\m_colo_new
+\permanent\tolerant\protected\def\defineglobalcolor[#1]#*[#2]%
{\iftok{#1}{#2}%
% maybe a warning
\else
\clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax
\colo_basics_synchronize{#1}%
\ifcase\c_colo_protection
- \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \protected\setgvalue{#1}{\colo_helpers_activate{#1}}%
\fi
\fi}
-\let\colo_basics_define_named\colo_basics_define
-
-\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change)
- {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
- \colo_basics_synchronize{#1}%
- \ifcase\c_colo_protection
- \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
- \fi}
+\let\definenamedcolor\definecolor
\def\colo_basics_defined_and_activated#1%
{\clf_defineprocesscolordummy{#1}% we could pass dummy here too
\colo_basics_synchronize{\v_colo_dummy_name}%
\colo_helpers_activate_dummy}
-\def\colo_basics_define_process
- {\ifthirdargument
- \expandafter\colo_basics_define_process_yes
- \else
- \expandafter\colo_basics_define_process_nop
- \fi}
-
-\def\colo_basics_define_process_yes[#1][#2][#3]%
- {\clf_defineprocesscolorlocal{#1}{\processcolorcomponents{#2},#3}\v_colo_freeze_state\relax
- \colo_basics_synchronize{#1}%
- \ifcase\c_colo_protection
- \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+\permanent\tolerant\protected\def\defineprocesscolor[#1]#*[#2]#*[#3]%
+ {\ifarguments\or
+ \colo_basics_define_process_wrapup{#1}\empty
+ \or
+ \colo_basics_define_process_wrapup{#1}{#2}%
+ \or % we could just pass #3 to clf_... also when it's empty ... todo after split
+ \colo_basics_define_process_wrapup{#1}{\processcolorcomponents{#2},#3}%
\fi}
-\def\colo_basics_define_process_nop[#1][#2][#3]%
+\def\colo_basics_define_process_wrapup#1#2%
{\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax
\colo_basics_synchronize{#1}%
\ifcase\c_colo_protection
- \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}%
+ \protected\setvalue{#1}{\colo_helpers_activate{#1}}%
\fi}
%D Spotcolors used setxvalue but that messes up currentcolor and probably no global
%D is needed either but they are global at the lua end (true argument) so we keep
%D that if only because spot colors often are a document wide property
-\def\colo_basics_define_spot[#1][#2][#3]%
+\permanent\tolerant\protected\def\definespotcolor[#1]#*[#2]#*[#3]%
{\clf_definespotcolorglobal{#1}{#2}{#3}%
\colo_basics_synchronize{#1}%
\ifcase\c_colo_protection
- \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \protected\setgvalue{#1}{\colo_helpers_activate{#1}}%
\fi}
-\def\colo_basics_define_multitone[#1][#2][#3][#4]%
+\permanent\tolerant\protected\def\definemultitonecolor[#1]#*[#2]#*[#3]#*[#4]%
{\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}%
\colo_basics_synchronize{#1}%
\ifcase\c_colo_protection
- \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}%
+ \protected\setgvalue{#1}{\colo_helpers_activate{#1}}%
\fi}
%D Transparencies (only):
-\def\colo_basics_define_transpancy[#1][#2]%
+\permanent\tolerant\protected\def\definetransparency[#1]#*[#2]%
{\clf_definetransparency{#1}{#2}}
-\def\colo_basics_define_transpancy_global[#1][#2]%
+\permanent\tolerant\protected\def\defineglobaltransparency[#1]#*[#2]%
{\clf_definetransparencyglobal{#1}{#2}}
% A goodie that replaces the startMPcolor hackery
@@ -971,10 +972,7 @@
%
% because the fractional definition results in a new definition.
-\unexpanded\def\defineintermediatecolor
- {\dotripleempty\colo_basics_define_intermediate}
-
-\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside []
+\permanent\tolerant\protected\def\defineintermediatecolor[#1]#*[#2]#*[#3]
{\colo_basics_define_intermediate_indeed[#1][#2][#3]}
\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]%
@@ -989,7 +987,7 @@
\v_colo_freeze_state
\relax
\colo_basics_synchronize{#1}%
- \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
+ \protected\setvalue{#1}{\colo_helpers_activate{#1}}}
%D Here is a more efficient helper for pgf:
%D
@@ -1044,7 +1042,7 @@
%D Switching to a color is done by means of the following command. Later on we will
%D explain the use of palets. We define ourselves a color conditional first.
-\def\doifelsecolor#1%
+\permanent\def\doifelsecolor#1%
{\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
\expandafter\firstoftwoarguments
\orelse\ifcsname\??colorattribute#1\endcsname
@@ -1055,7 +1053,7 @@
\let\doifcolorelse\doifelsecolor
-\def\doifcolor#1%
+\permanent\def\doifcolor#1%
{\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
\expandafter\firstofoneargument
\orelse\ifcsname\??colorattribute#1\endcsname
@@ -1088,14 +1086,13 @@
%D \stopregistercolor
%D \stoptyping
-\let\maintextcolor \empty
-\def\defaulttextcolor {black}
-\def\s!themaintextcolor{themaintextcolor}
+\let\maintextcolor \empty
+\def\defaulttextcolor{black}
-\unexpanded\def\inheritmaintextcolor
+\permanent\protected\def\inheritmaintextcolor
{\ifempty\maintextcolor\else\colo_helpers_activate\maintextcolor\fi}
-\unexpanded\def\onlyinheritmaintextcolor
+\permanent\protected\def\onlyinheritmaintextcolor
{\ifempty\maintextcolor
\deactivatecolor
\else
@@ -1113,9 +1110,8 @@
\colo_helpers_activate\maintextcolor
\clf_registermaintextcolor\thecolorattribute\maintextcolor\relax}
-\unexpanded\def\starttextcolor[#1]%
- {\doifsomething{#1}
- {\colo_helpers_switch_to_maintextcolor{#1}}}
+\permanent\protected\def\starttextcolor[#1]%
+ {\doifsomething{#1}{\colo_helpers_switch_to_maintextcolor{#1}}}
\let\stoptextcolor\relax
@@ -1140,16 +1136,6 @@
\def\colo_helpers_inherited_direct_ts#1{\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi}
\def\colo_helpers_inherited_direct_ta#1{\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi}
-% %def\colo_helpers_inherited_palet_cs#1#2{\csname\??colorsetter \ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
-% %def\colo_helpers_inherited_palet_ca#1#2{\csname\??colorattribute \ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
-% %def\colo_helpers_inherited_palet_ts#1#2{\csname\??transparencysetter \ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
-% %def\colo_helpers_inherited_palet_ta#1#2{\csname\??transparencyattribute\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
-%
-% \def\colo_helpers_inherited_palet_cs#1#2{\ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\lastnamedcs\fi}
-% \def\colo_helpers_inherited_palet_ca#1#2{\ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
-% \def\colo_helpers_inherited_palet_ts#1#2{\ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\lastnamedcs}
-% \def\colo_helpers_inherited_palet_ta#1#2{\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi}
-
\let\colo_helpers_set_value\setvalue
\appendtoks
@@ -1202,20 +1188,20 @@
%D Low level defs:
-\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\c_attr_color #2 }}
-\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\c_attr_color #2 }} % was not g
-\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\c_attr_transparency#2 }}
-\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\c_attr_transparency#2 }}
+\permanent\protected\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\c_attr_color #2 }}
+\permanent\protected\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\c_attr_color #2 }} % was not g
+\permanent\protected\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\c_attr_transparency#2 }}
+\permanent\protected\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\c_attr_transparency#2 }}
-\unexpanded\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
-\unexpanded\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
-\unexpanded\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
-\unexpanded\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+\permanent\protected\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\permanent\protected\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}}
+\permanent\protected\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
+\permanent\protected\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
-\unexpanded\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}}
-\unexpanded\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}}
-\unexpanded\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}}
-\unexpanded\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}}
+\permanent\protected\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}}
+\permanent\protected\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}}
+\permanent\protected\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}}
+\permanent\protected\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}}
%D \macros
%D {colorvalue, grayvalue}
@@ -1241,71 +1227,54 @@
\let\colorformatseparator\space
-\def\MPcolor#1%
+\permanent\def\MPcolor#1%
{\clf_mpcolor
\c_attr_colormodel
\colo_helpers_inherited_current_ca{#1} %
\colo_helpers_inherited_current_ta{#1} }
-\def\MPcoloronly#1%
+\permanent\def\MPcoloronly#1%
{\clf_mpcolor
\c_attr_colormodel
\colo_helpers_inherited_current_ca{#1} %
\zerocount}
-\def\MPtransparency#1%
+\permanent\def\MPtransparency#1%
{\clf_mpcolor
\zerocount
\zerocount
\colo_helpers_inherited_current_ta{#1} }
-\def\MPoptions#1%
+\permanent\def\MPoptions#1%
{\clf_mpoptions
\c_attr_colormodel
\colo_helpers_inherited_current_ca{#1} %
\colo_helpers_inherited_current_ta{#1} }
-\def\thecolormodelattribute {\the\c_attr_colormodel}
+\permanent\def\thecolormodelattribute {\the\c_attr_colormodel}
-\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
-\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
+\permanent\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
+\permanent\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
-\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
-\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
-
-% \def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} }
-% \def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} }
-% \def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} }
-%
-% \def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} }
-% \def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} }
-% \def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} }
-%
-% \def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}}
-% \def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}}
-%
-% \def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} }
-% \def\doifelsedrawingblack {\clf_doifelsedrawingblack}
-%
-% \let\doifblackelse \doifelseblack
-% \let\doifdrawingblackelse \doifelsedrawingblack
+\permanent\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi}
+\permanent\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi}
-\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}}
-\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}}
-\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}}
+\permanent\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}}
+\permanent\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}}
+\permanent\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}}
-\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}}
-\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}}
-\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}}
+\permanent\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}}
+\permanent\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}}
+\permanent\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}}
-\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}}
-\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}}
+\permanent\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}}
+\permanent\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}}
-\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}}
-\def\doifelsedrawingblack {\clf_doifelsedrawingblack}
+\permanent\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}}
+\permanent\def\doifelsedrawingblack {\clf_doifelsedrawingblack}
-\let\doifblackelse \doifelseblack
-\let\doifdrawingblackelse \doifelsedrawingblack
+\aliased\let\doifblackelse \doifelseblack
+\aliased\let\doifdrawingblackelse \doifelsedrawingblack
%D \macros
%D {forcecolorhack}
@@ -1327,15 +1296,14 @@
% \normal added else fails in metafun manual (leaders do a hard scan)
-% \unexpanded\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed !
+% \protected\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed !
%
% I really need to sort this out!
-\unexpanded\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed !
+\permanent\protected\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed !
-%D We default to the colors defined in \type {colo-imp-rgb} and
-%D support both \RGB\ and \CMYK\ output. Transparencies are defined
-%D here:
+%D We default to the colors defined in \type {colo-imp-rgb} and support both \RGB\
+%D and \CMYK\ output. Transparencies are defined here:
\definecolor[black][s=0]
\definecolor[white][s=1]
diff --git a/tex/context/base/mkiv/cont-log.mkiv b/tex/context/base/mkiv/cont-log.mkiv
index 42de5b434..3dbfdc604 100644
--- a/tex/context/base/mkiv/cont-log.mkiv
+++ b/tex/context/base/mkiv/cont-log.mkiv
@@ -302,7 +302,7 @@
\def\LuaTeX {LuaTeX}%
\def\LuajitTeX {LuajitTeX}%
\def\LuaMetaTeX{LuaMetaTeX}%
- \let\wordboundary\empty
+ %\let\wordboundary\empty % primitive so we need to promote it to frozen (orjust preroll)
\to \everysimplifycommands
\protect \endinput
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index ca98de02e..d14c6b9c7 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.09.20 22:59}
+\newcontextversion{2020.10.30 22:24}
%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
@@ -35,10 +35,16 @@
\ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi
\appendtoks
- \let\t\mathtext
- \let\w\mathword
+ \overloaded\let\t\mathtext
+ \overloaded\let\w\mathword
\to \everymathematics
+\pushoverloadmode
+ % charts needs these
+ \overloaded\unletfrozen\name % for now
+ \overloaded\frozen\let\type\type
+\popoverloadmode
+
%D We're done.
\protect \endinput
diff --git a/tex/context/base/mkiv/cont-run.lua b/tex/context/base/mkiv/cont-run.lua
index 3fef61672..eb0e143d5 100644
--- a/tex/context/base/mkiv/cont-run.lua
+++ b/tex/context/base/mkiv/cont-run.lua
@@ -190,9 +190,15 @@ else
end
-local preparejob preparejob = function() -- tricky: we need a hook for this
+local function processjob()
+
+ tokens.setters.macro("processjob","") -- make a
+
+ environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
local arguments = environment.arguments
+ local suffix = environment.suffix
+ local filename = environment.filename -- hm, not inputfilename !
environment.lmtxmode = CONTEXTLMTXMODE
@@ -207,25 +213,21 @@ local preparejob preparejob = function() -- tricky: we need a hook for this
}
end
- preparejob = function() end
-
- job.prepare = preparejob
+ if CONTEXTLMTXMODE then
-end
+ local overloadmode = arguments.overloadmode
-job.prepare = preparejob
-
-local function processjob()
-
- tokens.setters.macro("processjob","") -- make a
-
- environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
+ if overloadmode == "warning" then
+ overloadmode = 3 -- 5
+ elseif overloadmode == "error" then
+ overloadmode = 4 -- 6
+ else
+ overloadmode = tonumber(overloadmode) or 0
+ end
- local arguments = environment.arguments
- local suffix = environment.suffix
- local filename = environment.filename -- hm, not inputfilename !
+ tex.set("overloadmode",overloadmode)
- preparejob()
+ end
if not filename or filename == "" then
-- skip
diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv
index f841ce530..fba9cfaa9 100644
--- a/tex/context/base/mkiv/cont-run.mkiv
+++ b/tex/context/base/mkiv/cont-run.mkiv
@@ -53,4 +53,16 @@
\unexpanded\def\blocksynctexfile[#1]%
{\processcommacommand{#1}\synctexblockfilename}
+\ifcase\contextlmtxmode
+ \def\continuewhenlmtxmode
+ {\starttext
+ \startTEXpage[\c!offset=2ex,\c!foregroundstyle=\tttf]%
+ This file needs \LuaMetaTeX\ and \ConTeXt\ \LMTX.%
+ \stopTEXpage
+ \stoptext
+ \endinput}
+\else
+ \let\continuewhenlmtxmode\relax
+\fi
+
\protect \endinput
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 45f52a9c5..d22459a4b 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.09.20 22:59}
+\edef\contextversion{2020.10.30 22:24}
%D Kind of special:
diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl
index dcf733d2e..793fc4d14 100644
--- a/tex/context/base/mkiv/context.mkxl
+++ b/tex/context/base/mkiv/context.mkxl
@@ -29,7 +29,12 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.09.20 22:59}
+\edef\contextversion{2020.10.30 22:24}
+
+%overloadmode 1 % check frozen / warning
+%overloadmode 2 % check frozen / error
+%overloadmode 3 % check frozen, primitive, permanent / warning
+\overloadmode 4 % check frozen, primitive, permanent / error
%D Kind of special:
@@ -89,10 +94,10 @@
\loadmarkfile{luat-lib}
\loadmarkfile{luat-soc}
-\loadmarkfile{catc-ini}
+\loadmkxlfile{catc-ini}
\loadmarkfile{catc-act}
\loadmarkfile{catc-def}
-\loadmarkfile{catc-ctx}
+\loadmkxlfile{catc-ctx}
\loadmarkfile{catc-sym}
\loadmarkfile{toks-ini}
@@ -129,12 +134,12 @@
\loadmarkfile{supp-dir}
-\loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini
-\loadmarkfile{char-ini} % tex / context specific
-\loadmarkfile{char-act} % even more specific
+\loadmarkfile{char-utf}
+\loadmkxlfile{char-ini}
+\loadmarkfile{char-act}
-\loadmarkfile{mult-ini}
-\loadmarkfile{mult-sys}
+\loadmkxlfile{mult-ini}
+\loadmkxlfile{mult-sys}
\loadmkxlfile{mult-aux} % LMTX
\loadmarkfile{mult-def}
\loadmarkfile{mult-chk}
@@ -146,10 +151,10 @@
\loadmarkfile{toks-aux}
-\loadmarkfile{attr-ini}
+\loadmkxlfile{attr-ini}
\loadmarkfile{core-ini}
-\loadmarkfile{core-env}
+\loadmkxlfile{core-env}
\loadmarkfile{layo-ini}
@@ -171,7 +176,7 @@
\loadmarkfile{attr-col}
\loadmarkfile{attr-lay}
\loadmarkfile{attr-neg}
-\loadmarkfile{attr-eff}
+\loadmkxlfile{attr-eff}
\loadmarkfile{attr-mkr}
\loadmarkfile{trac-tex}
@@ -193,16 +198,16 @@
\loadmarkfile{typo-inj}
-\loadmkvifile{file-syn}
+\loadmklxfile{file-syn}
\loadmkvifile{file-mod}
\loadmarkfile{core-sys}
-\loadmarkfile{core-con}
+\loadmkxlfile{core-con}
\loadmarkfile{cont-fil}
\loadmarkfile{regi-ini}
-\loadmarkfile{enco-ini}
+\loadmkxlfile{enco-ini}
\loadmkxlfile{hand-ini}
\loadmkxlfile{lang-ini} % LMTX
@@ -240,7 +245,7 @@
\loadmkvifile{pack-bck}
\loadmarkfile{pack-fen}
-\loadmarkfile{lxml-ini}
+\loadmkxlfile{lxml-ini}
\loadmarkfile{lxml-sor}
\loadmkvifile{typo-prc}
@@ -253,9 +258,9 @@
\loadmarkfile{strc-doc}
\loadmarkfile{strc-num}
\loadmarkfile{strc-mar}
-\loadmarkfile{strc-sbe}
+\loadmkxlfile{strc-sbe}
\loadmkvifile{strc-lst}
-\loadmarkfile{strc-sec}
+\loadmkxlfile{strc-sec}
\loadmarkfile{strc-pag} % hm, depends on core-num
\loadmarkfile{strc-ren}
\loadmarkfile{strc-xml}
@@ -284,29 +289,29 @@
\loadmklxfile{strc-itm} % LMTX
-\loadmkvifile{strc-con}
-\loadmkvifile{strc-des}
-\loadmkvifile{strc-enu}
+\loadmklxfile{strc-con}
+\loadmklxfile{strc-des}
+\loadmklxfile{strc-enu}
\loadmarkfile{strc-ind}
-\loadmarkfile{strc-lab}
-\loadmarkfile{strc-syn}
+\loadmkxlfile{strc-lab}
+\loadmkxlfile{strc-syn}
% \loadmarkfile{core-sys}
\loadmarkfile{page-var}
\loadmkvifile{page-otr}
-\loadmarkfile{page-ini}
+\loadmkxlfile{page-ini}
\loadmarkfile{page-ins}
\loadmarkfile{page-fac}
\loadmarkfile{page-brk}
\loadmarkfile{page-col}
\loadmarkfile{page-inf}
\loadmarkfile{page-flt}
-\loadmarkfile{page-bck}
+\loadmkxlfile{page-bck}
\loadmarkfile{page-not}
\loadmarkfile{page-one}
-\loadmarkfile{page-lay}
+\loadmkxlfile{page-lay}
\loadmkvifile{page-box}
\loadmklxfile{page-txt} % LMTX
\loadmarkfile{page-sid} % when
@@ -371,7 +376,7 @@
\loadmkvifile{font-lib} % way too late but after language
\loadmklxfile{font-fil} % LMTX
\loadmkvifile{font-var}
-\loadmkvifile{font-fea}
+\loadmklxfile{font-fea}
\loadmklxfile{font-mat} % LMTX
\loadmklxfile{font-ini} % LMTX
\loadmklxfile{font-sym} % LMTX
@@ -391,18 +396,18 @@
\loadmarkfile{typo-tal}
\loadmarkfile{typo-par} % par builders (uses fonts)
-\loadmarkfile{tabl-com}
+\loadmkxlfile{tabl-com}
\loadmarkfile{tabl-pln}
-\loadmarkfile{tabl-tab} % thrd-tab stripped and merged
+\loadmkxlfile{tabl-tab} % thrd-tab stripped and merged
\loadmkxlfile{tabl-tbl} % LMTX
\loadmkxlfile{tabl-ntb} % LMTX
-\loadmarkfile{tabl-nte}
-\loadmarkfile{tabl-ltb}
-\loadmarkfile{tabl-frm}
+\loadmkxlfile{tabl-nte}
+\loadmkxlfile{tabl-ltb}
+\loadmkxlfile{tabl-frm}
\loadmarkfile{tabl-tsp}
-\loadmkvifile{tabl-xtb}
+\loadmklxfile{tabl-xtb}
\loadmarkfile{tabl-mis}
\loadmarkfile{typo-lan}
@@ -413,7 +418,7 @@
\loadmkxlfile{blob-ini}
-\loadmarkfile{trac-vis}
+\loadmkxlfile{trac-vis}
\loadmarkfile{trac-jus}
\loadmarkfile{typo-cln}
@@ -430,7 +435,7 @@
\loadmarkfile{typo-drp}
\loadmarkfile{typo-fln}
\loadmarkfile{typo-sus}
-\loadmarkfile{typo-lig}
+\loadmkxlfile{typo-lig}
\loadmarkfile{typo-chr}
\loadmarkfile{typo-rub}
\loadmkivfile{typo-fkr}
@@ -463,7 +468,7 @@
\loadmarkfile{page-mrk} % depends on mp
\loadmarkfile{page-flw}
-\loadmarkfile{page-spr}
+\loadmkxlfile{page-spr}
\loadmarkfile{page-plg}
\loadmarkfile{page-str}
@@ -474,13 +479,13 @@
%loadmarkfile{anch-snc} % when needed this one will be redone
\loadmkxlfile{math-ini} % way after font-pre !
-\loadmarkfile{math-pln}
+\loadmkxlfile{math-pln}
\loadmarkfile{math-for}
\loadmarkfile{math-def} % also saves some meanings
-\loadmarkfile{math-ali}
+\loadmkxlfile{math-ali}
%loadmarkfile{math-arr}
\loadmkvifile{math-stc}
-\loadmarkfile{math-frc}
+\loadmkxlfile{math-frc}
\loadmarkfile{math-mis}
\loadmarkfile{math-scr}
\loadmarkfile{math-int}
@@ -498,7 +503,7 @@
\loadmarkfile{strc-mat}
\loadmarkfile{chem-ini}
-\loadmarkfile{chem-str}
+\loadmkxlfile{chem-str}
\loadmarkfile{typo-scr}
\loadmarkfile{phys-dim}
@@ -506,12 +511,12 @@
\loadmarkfile{node-rul} % beware, defined \underbar so after math
\loadmkvifile{font-sol} % font solutions
-\loadmkvifile{strc-not}
+\loadmklxfile{strc-not}
\loadmkvifile{strc-lnt}
\loadmkivfile{strc-tnt}
\loadmkivfile{strc-usr}
-\loadmarkfile{pack-com}
+\loadmkxlfile{pack-com}
\loadmarkfile{typo-del}
\loadmarkfile{grph-trf}
@@ -519,9 +524,9 @@
\loadmarkfile{grph-fig}
\loadmarkfile{grph-raw}
\loadmarkfile{grph-rul}
-\loadmarkfile{grph-pat}
+\loadmkxlfile{grph-pat}
-\loadmarkfile{pack-box}
+\loadmkxlfile{pack-box}
\loadmarkfile{pack-bar}
\loadmarkfile{page-app}
\loadmarkfile{meta-fig}
@@ -611,4 +616,12 @@
\ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkxl","\contextbanner")}% can become automatic
\to \everydump
+% some day:
+%
+% \prependtoks
+% \overloadmode 255
+% \to \everyjob
+
+\overloadmode 0 % for now
+
\errorstopmode \dump \endinput
diff --git a/tex/context/base/mkiv/core-con.mkiv b/tex/context/base/mkiv/core-con.mkiv
index fd45aed6c..da2648e87 100644
--- a/tex/context/base/mkiv/core-con.mkiv
+++ b/tex/context/base/mkiv/core-con.mkiv
@@ -223,8 +223,12 @@
%D \showsetup{month}
%D \showsetup{MONTH}
+\pushoverloadmode
+
\let\month\monthlong
+\popoverloadmode
+
\unexpanded\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}}
\unexpanded\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}}
\unexpanded\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}}
diff --git a/tex/context/base/mkiv/core-con.mkxl b/tex/context/base/mkiv/core-con.mkxl
new file mode 100644
index 000000000..0f836f0cc
--- /dev/null
+++ b/tex/context/base/mkiv/core-con.mkxl
@@ -0,0 +1,1013 @@
+%D \module
+%D [ file=core-con,
+%D version=1997.26.08,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Conversion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Conversion}
+
+\registerctxluafile{core-con}{}
+
+% todo: iso date ranges (from/to)
+
+\unprotect
+
+\ifdefined\currentlanguage \else \let\currentlanguage\empty \fi
+\ifdefined\labeltext \else \let\labeltext \firstofoneargument \fi
+
+%D This module deals with all kind of conversions from numbers and dates. I
+%D considered splitting this module in a support one and a core one, but to keep
+%D things simple as well as preserve the overview, I decided against splitting.
+
+\let\spr\firstofoneargument % separator
+\let\stp\firstofoneargument % stopper
+
+% needed for arab:
+
+\permanent\protected\def\isolateseparators % even works with list separator overloading
+ {\def\spr##1{{##1}}% % we can probably best mess around with zwj
+ \def\stp##1{{##1}}} % and friends
+
+%D \macros
+%D {numbers}
+%D
+%D First we deal with the dummy conversion of numbers using the \TEX\ primitive
+%D \type{\number}. The uppercase alternative is only there for compatibility with
+%D the other conversion macros. We could do without \type{#1} but this way we get
+%D rid of unwanted braces. For the savety we also define a non||sence uppercase
+%D alternative.
+%D
+%D \showsetup{numbers}
+%D
+%D \starttyping
+%D \def\numbers#1{\number#1}
+%D \def\Numbers#1{\number#1}
+%D \stoptyping
+%D
+%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear,
+%D unless we use:
+
+\permanent\def\numbers#1{\purenumber{#1}}
+\permanent\def\Numbers#1{\purenumber{#1}}
+
+%D \macros
+%D {romannumerals,Romannumerals}
+%D
+%D \TEX\ the program uses a rather tricky conversion from numbers to their roman
+%D counterparts. This conversion could of course be programmed in \TEX\ itself, but
+%D I guess Knuth found the programming trick worth presenting.
+%D
+%D \showsetup{romannumerals}
+%D \showsetup{Romannumerals}
+
+\permanent\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax}
+\permanent\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax}
+
+%D Arabic etc:
+
+\permanent\def\abjadnumerals #1{\clf_abjadnumerals \numexpr#1\relax}
+\permanent\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax}
+\permanent\def\abjadnaivenumerals#1{\clf_alphabetic \numexpr#1\relax{arabic}} % okay?
+
+\permanent\def\hebrewnumerals #1{\clf_hebrewnumerals\numexpr#1\relax}
+\aliased \let\yiddishnumerals \hebrewnumerals
+
+\permanent\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new
+\permanent\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new
+
+\permanent\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}}
+\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}}
+
+\permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}}
+\permanent\def\devanagarinumerals#1{\clf_alphabetic\numexpr#1\relax{devanagari}}
+\permanent\def\gurmurkhinumerals #1{\clf_alphabetic\numexpr#1\relax{gurmurkhi}}
+\permanent\def\gujaratinumerals #1{\clf_alphabetic\numexpr#1\relax{gujarati}}
+\permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}}
+\permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}}
+\permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}}
+\permanent\def\arabicnumerals #1{\clf_alphabetic\numexpr#1\relax{arabic}}
+\permanent\def\persiannumerals #1{\clf_alphabetic\numexpr#1\relax{persian}}
+\permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}}
+\permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}}
+
+\aliased \let\arabicexnumerals \persiannumerals
+
+\permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}}
+\permanent\def\koreannumeralsp #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}}
+\permanent\def\koreannumeralsc #1{\clf_alphabetic\numexpr#1\relax{korean-circle}}
+
+\aliased \let\koreanparentnumerals \koreannumeralsp
+\aliased \let\koreanparenthesisnumerals\koreannumeralsp
+\aliased \let\koreancirclenumerals \koreannumeralsc
+
+\permanent\def\chinesenumerals #1{\clf_chinesenumerals\numexpr#1\relax{normal}}
+\permanent\def\chinesecapnumerals#1{\clf_chinesenumerals\numexpr#1\relax{cap}}
+\permanent\def\chineseallnumerals#1{\clf_chinesenumerals\numexpr#1\relax{all}}
+
+%D \macros
+%D {character,Character}
+%D
+%D Converting a number into a character can of course only be done with numbers
+%D less or equal to~26. At the cost of much more macros a faster conversion is
+%D possible, using:
+%D
+%D \starttyping
+%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
+%D \stoptyping
+%D
+%D But we prefer a simpel \type{\case}.
+%D
+%D \showsetup{character}
+%D \showsetup{Character}
+
+\def\unknowncharacter{-} % else in lists \relax
+
+\permanent\def\character#1{\clf_character\numexpr#1\relax}
+\permanent\def\Character#1{\clf_Character\numexpr#1\relax}
+
+%D \macros
+%D {characters,Characters}
+%D
+%D Converting large numbers is supported by the next two macros. This time we
+%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$.
+%D
+%D \showsetup{characters}
+%D \showsetup{Characters}
+
+\permanent\def\characters#1{\clf_characters\numexpr#1\relax}
+\permanent\def\Characters#1{\clf_Characters\numexpr#1\relax}
+
+%D \macros
+%D {greeknumerals,Greeknumerals}
+%D
+%D Why should we only honour the romans, and not the greek?
+
+% \let\greeknumerals\gobbleoneargument
+% \let\Greeknumerals\gobbleoneargument
+
+%D \macros
+%D {oldstylenumerals,oldstyleromannumerals}
+%D
+%D These conversions are dedicated to Frans Goddijn.
+
+\permanent\protected\def\oldstylenumerals#1%
+ {\begingroup
+ \os\number#1%
+ \endgroup}
+
+\permanent\protected\def\oldstyleromannumerals#1% will become obsolete
+ {\dontleavehmode
+ \hbox\bgroup
+ \ss\txx
+ \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}%
+ \scratchwidth \wd\scratchbox
+ \scratchheight\ht\scratchbox
+ \scratchdimen .1\exheight
+ \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax
+ \hskip-\scratchwidth
+ \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen
+ \hskip-\scratchwidth
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {protectconversion}
+%D
+%D The previous two commands are not robust enough to be passed to \type
+%D {\write} en \type{\message}. That's why we introduce:
+
+\permanent\protected\def\protectconversion
+ {\let\doconvertcharacters\firstofoneargument}
+
+%D \macros
+%D {normaltime,normalyear,normalmonth,normalday}
+%D
+%D The last part of this module is dedicated to converting dates. Because we want to
+%D use as meaningful commands as possible, and because \TEX\ already uses up some of
+%D those, we save the original meanings.
+
+% \savenormalmeaning\time
+% \savenormalmeaning\year
+% \savenormalmeaning\month
+% \savenormalmeaning\day
+
+%D \macros
+%D {month,MONTH}
+%D
+%D Converting the month number into a month name is done using a case statement,
+%D abstact values and the label mechanism. This way users can easily redefine a
+%D label from for instance german into austrian.
+%D
+%D \starttyping
+%D \setuplabeltext [de] [january=J\"anner]
+%D \stoptyping
+%D
+%D Anyhow, the conversion looks like:
+
+\permanent\protected\def\monthlong #1{\clf_monthname\numexpr#1\relax}
+\permanent\protected\def\monthshort#1{\clf_monthmnem\numexpr#1\relax}
+\permanent\protected\def\daylong #1{\clf_dayname\numexpr#1\relax}
+\permanent\protected\def\dayshort #1{\clf_daymnem\numexpr#1\relax}
+\aliased \let\convertmonth\monthlong % for old times sake
+
+%D We redefine the \TEX\ primitive \type{\month} as:
+%D
+%D \showsetup{month}
+%D \showsetup{MONTH}
+
+\pushoverloadmode
+
+\aliased\let\month\monthlong
+
+\popoverloadmode
+
+\permanent\protected\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}}
+\permanent\protected\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}}
+\permanent\protected\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}}
+
+%D We never explicitly needed this, but Tobias Burnus pointed out that it would be
+%D handy to convert to the day of the week. In doing so, we have to calculate the
+%D total number of days, taking leapyears into account. For those who are curious:
+%D
+%D \startitemize[packed]
+%D \item years that can be divided by 4 are leapyears
+%D \item exept years that can be divided by 100
+%D \item unless years can be divided by 400
+%D \stopitemize
+
+%D \macros
+%D {weekday,WEEKDAY}
+%D
+%D The first one is sort of redundant. It takes the day number argument.
+%D
+%D \showsetup{weekday}
+%D \showsetup{WEEKDAY}
+
+\permanent\protected\def\weekday #1{\clf_dayname\numexpr#1\relax}
+\permanent\protected\def\WEEKDAY #1{\WORD{\clf_dayname\numexpr#1\relax}}
+\permanent\protected\def\DAYLONG #1{\WORD{\clf_dayname\numexpr#1\relax}}
+\permanent\protected\def\DAYSHORT#1{\WORD{\clf_daymnem\numexpr#1\relax}}
+
+%D \macros
+%D {getdayoftheweek, dayoftheweek}
+
+\newcount\normalweekday
+
+\permanent \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax} % name
+\permanent\protected\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number
+
+%D Using this macro in
+%D
+%D \startbuffer
+%D monday: \dayoftheweek {4} {5} {1992}
+%D friday: \dayoftheweek {16} {6} {1995}
+%D monday: \dayoftheweek {25} {8} {1997}
+%D saturday: \dayoftheweek {30} {8} {1997}
+%D tuesday: \dayoftheweek {2} {1} {1996}
+%D tuesday: \dayoftheweek {7} {1} {1997}
+%D tuesday: \dayoftheweek {13} {1} {1998}
+%D friday: \dayoftheweek {1} {1} {2000}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The macro \type {\getdayoftheweek} can be used to calculate the number \type
+%D {\normalweekday}.
+
+%D \macros
+%D {doifleapyearelse,
+%D getdayspermonth}
+%D
+%D Sometimes we need to know if we're dealing with a leapyear, so here is a
+%D testmacro:
+%D
+%D \starttyping
+%D \doifleapyearelse{year}{yes}{no}
+%D \stoptyping
+%D
+%D An example of its use can be seen in the macro
+%D
+%D \starttyping
+%D \getdayspermonth{year}{month}
+%D \stoptyping
+%D
+%D The number of days is available in the macro \type {\numberofdays}.
+
+\permanent\def\doifelseleapyear#1% expandable check
+ {\clf_doifelseleapyear\numexpr#1\relax}
+
+\aliased\let\doifleapyearelse\doifelseleapyear
+
+\permanent\protected\def\getdayspermonth#1#2%
+ {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}}
+
+\permanent\def\dayspermonth#1#2%
+ {\clf_nofdays\numexpr#1\relax\numexpr#2\relax}
+
+% \dayoftheweek{2006}{9}{15}
+% \doifleapyearelse{2000}{OK}{NOT OK}
+% \doifleapyearelse{2100}{NOT OK}{OK}
+% \doifleapyearelse{2004}{OK}{NOT OK}
+% \doifleapyearelse{2003}{NOT OK}{OK}
+% \dayspermonth{2000}{2}
+% [\the\normaltime=\the\time]
+
+%D \macros
+%D {currentdate, rawdate, date}
+%D
+%D We use these conversion macros in the date formatting macro:
+%D
+%D \showsetup{currentdate}
+%D
+%D This macro takes care of proper spacing and delivers for instance:
+%D
+%D \startbuffer
+%D \currentdate[weekday,day,month,year]
+%D \currentdate[WEEKDAY,day,MONTH,year]
+%D \stopbuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D depending of course on the keywords. Here we gave:
+%D
+%D \typebuffer
+%D
+%D If needed one can also add non||keywords, like in
+%D
+%D \startbuffer
+%D \currentdate[dd,--,mm,--,yy]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or typeset: \getbuffer.
+%D
+%D When no argument is passed, the current date is given as specified per
+%D language (using \type{\installlanguage}).
+%D
+%D \showsetup{currentdate}
+%D
+%D \startbuffer
+%D \date
+%D \date[d=12,m=12,y=1998][weekday]
+%D \date[d=12,m=12,y=1998]
+%D \stopbuffer
+%D
+%D We can also typeset arbitrary dates, using the previous
+%D command.
+%D
+%D \typebuffer
+%D
+%D The date is specified by one character keys. When no date is given, we get the
+%D current date.
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+%D \starttabulate[|l|l|]
+%D \HL
+%D \NC year \NC (\currentdate[year]) \NC\NR
+%D \NC yy \NC (\currentdate[yy]) \NC\NR
+%D \NC y \NC (\currentdate[y]) \NC\NR
+%D \NC Y \NC (\currentdate[Y]) \NC\NR
+%D \HL
+%D \NC month \NC (\currentdate[month]) \NC\NR
+%D \NC mm \NC (\currentdate[mm]) \NC\NR
+%D \NC m \NC (\currentdate[m]) \NC\NR
+%D \NC M \NC (\currentdate[M]) \NC\NR
+%D \HL
+%D \NC day \NC (\currentdate[day]) \NC\NR
+%D \NC dd \NC (\currentdate[dd]) \NC\NR
+%D \NC d \NC (\currentdate[d]) \NC\NR
+%D \NC D \NC (\currentdate[D]) \NC\NR
+%D \HL
+%D \NC weekday \NC (\currentdate[weekday]) \NC\NR
+%D \NC w \NC (\currentdate[w]) \NC\NR
+%D \NC W \NC (\currentdate[W]) \NC\NR
+%D \HL
+%D \NC referral \NC (\currentdate[referral]) \NC\NR
+%D \HL
+%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR
+%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR
+%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR
+%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR
+%D \HL
+%D \stoptabulate
+%D
+%D \startbuffer
+%D (\currentdate[D,.,M,.,Y])
+%D (\currentdate[day,month,year])
+%D (\currentdate[day,+,month,+,year])
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Some indirectness and abstraction:
+%D
+%D \starttyping
+%D \definedate[crap][year]
+%D \currentdate[crap]
+%D \stoptyping
+
+\installcorenamespace{date}
+
+\permanent\tolerant\protected\def\definedate[#1]#*[#2]%
+ {\ifarguments\else\setvalue{\??date#1}{#2}\fi}
+
+\def\syst_converters_check_date_specification#1%
+ {\ifcsname\??date#1\endcsname
+ \edef#1{\lastnamedcs}%
+ \fi}
+
+\newtoks\everycurrentdate
+
+\permanent\tolerant\protected\def\currentdate[#1]%
+ {\dontleavehmode
+ \begingroup
+ \the\everycurrentdate
+ \edef\forceddatespecification{#1}%
+ \syst_converters_check_date_specification\forceddatespecification
+ \syst_converters_check_date_specification\currentdatespecification
+ \clf_currentdate
+ {\forceddatespecification}{\currentdatespecification}{\labellanguage}%
+ \normalyear\normalmonth\normalday
+ \endgroup}
+
+\permanent\tolerant\protected\def\date[#1][#2]% sets the date !
+ {\dontleavehmode
+ \ifparameter#1\or
+ \begingroup
+ \letdummyparameter\c!d\normalday
+ \letdummyparameter\c!m\normalmonth
+ \letdummyparameter\c!y\normalyear
+ \getdummyparameters[#1]%
+ \normalexpanded
+ {\endgroup
+ \normalday \number\directdummyparameter\c!d\relax
+ \normalmonth\number\directdummyparameter\c!m\relax
+ \normalyear \number\directdummyparameter\c!y\relax}%
+ \fi
+ \begingroup
+ \the\everycurrentdate
+ \edef\forceddatespecification{#2}%
+ \syst_converters_check_date_specification\forceddatespecification
+ \syst_converters_check_date_specification\currentdatespecification
+ \clf_currentdate
+ {\forceddatespecification}{\currentdatespecification}{\labellanguage}%
+ \normalyear\normalmonth\normalday
+ \endgroup}
+
+\permanent\def\rawdate[#1]% expandable and no labels
+ {\clf_currentdate
+ {#1}{\currentdatespecification}{}%
+ \normalyear\normalmonth\normalday}
+
+%D \macros
+%D {currenttime}
+%D
+%D The currenttime is actually the jobtime. You can specify a pattern similar
+%D to the previous date macro using the keys \type {h}, \type {m} and a separator.
+
+\permanent\protected\def\calculatecurrenttime
+ {\edef\currenthour {\clf_hour }%
+ \edef\currentminute{\clf_minute}%
+ \edef\currentsecond{\clf_second}}
+
+\let\currenthour \!!plusone
+\let\currentminute\!!plusone
+\let\currentsecond\!!plusone
+
+% \def\currenttimespecification{h,:,m}
+
+\permanent\protected\def\currenttime
+ {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop}
+
+\protected\def\syst_converters_current_time_yes[#1]%
+ {\calculatecurrenttime
+ \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
+
+\protected\def\syst_converters_current_time_nop
+ {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}}
+
+%D Because we're dealing with dates, we also introduce a few day loops:
+%D
+%D \starttyping
+%D \processmonth{year}{month}{command}
+%D \processyear{year}{command}{before}{after}
+%D \stoptyping
+%D
+%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday}
+%D can be used for for date manipulations.
+
+\permanent\protected\def\processmonth#1#2#3% year month command
+ {\begingroup
+ \getdayspermonth{#1}{#2}%
+ \dostepwiserecurse\plusone\numberofdays\plusone
+ {\normalyear #1\relax
+ \normalmonth#2\relax
+ \normalday \recurselevel\relax
+ #3}%
+ \endgroup}
+
+\def\lastmonth{12} % can be set to e.g. 1 when testing
+
+\permanent\protected\def\processyear#1#2#3#4% year command before after
+ {\begingroup
+ \dorecurse\lastmonth
+ {\normalyear #1\relax
+ \normalmonth\recurselevel\relax
+ #3\processmonth\normalyear\normalmonth{#2}#4}%
+ \endgroup}
+
+%D \macros
+%D {defineconversion, convertnumber}
+%D
+%D Conversion involves the macros that we implemented earlier in this module.
+%D
+%D \showsetup{defineconversion}
+%D \showsetup{convertnumber}
+%D
+%D We can feed this command with conversion macros as well as a set of conversion
+%D symbols. Both need a bit different treatment.
+%D
+%D \starttyping
+%D \defineconversion [roman] [\romannumerals]
+%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
+%D \stoptyping
+%D
+%D You can define a language dependent conversion with:
+%D
+%D \starttyping
+%D \defineconversion [en] [whatever] [\something]
+%D \stoptyping
+
+\installcorenamespace {conversion}
+\installcorenamespace {conversionarguments}
+\installcorenamespace {conversionwords}
+
+%D It might be better to move more to \LUA\ as we also need conversion there and
+%D doublicating logic doesn't make things cleaner. It means that all conversions
+%D will get a language argument too. However, we permit definitions at the \TEX\ end
+%D so we have to provide some hybrid method.
+
+% checkedconversion(method,n,language)
+
+\protected\def\defineconversion
+ {\dotripleempty\syst_converters_define_conversion}
+
+\def\syst_converters_define_conversion[#1][#2][#3]% from now on global (maybe local again some day)
+ {\ifthirdargument
+ \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}%
+ \else
+ \syst_converters_define_conversion_indeed{#1}{#1}{#2}%
+ \fi}
+
+\def\syst_converters_define_conversion_indeed#1#2#3%
+ {\doifelseinstring{,}{\detokenize{#3}}
+ {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols
+ \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}}
+ {\setgvalue{\??conversion#1}{#3}}}
+
+\def\syst_converters_checked_conversion#1#2%
+ {\clf_checkedconversion{#1}\numexpr#2\relax}
+
+%D If a conversion is just a font switch then we need to make sure that the number
+%D is indeed ends up as number in the input, so we need to handle the second
+%D argument.
+
+\permanent\def\convertnumber#1#2% expandable
+ {\csname\??conversionarguments
+ \ifcsname\??conversion\currentlanguage#1\endcsname1\else
+ \ifcsname\??conversion #1\endcsname2\else
+ 3\fi\fi
+ \endcsname{#1}{\number#2}}
+
+\protected\def\uconvertnumber % unexpandable
+ {\convertnumber}
+
+\setvalue{\??conversionarguments1}#1{\csname\??conversion\currentlanguage#1\endcsname}
+\setvalue{\??conversionarguments2}#1{\csname\??conversion #1\endcsname}
+\letvalue{\??conversionarguments3}\syst_converters_checked_conversion
+
+% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check
+% if we have definitions that are not matched at the lua end .. eventually we might do
+% that when more shows up
+
+\permanent\def\doifelseconversiondefined#1% expandable
+ {\ifcsname\??conversion\currentlanguage#1\endcsname
+ \expandafter\firstoftwoarguments
+ \orelse\ifcsname\??conversion#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\permanent\def\doifelseconversionnumber#1#2% expandable
+ {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\aliased\let\doifconversiondefinedelse\doifelseconversiondefined
+\aliased\let\doifconversionnumberelse \doifelseconversionnumber
+
+%D Handy.
+
+\setvalue{\??conversionwords\v!one }{1}
+\setvalue{\??conversionwords\v!two }{2}
+\setvalue{\??conversionwords\v!three}{3}
+\setvalue{\??conversionwords\v!four }{4}
+\setvalue{\??conversionwords\v!five }{5}
+
+%permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
+\permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi}
+
+% \defineconversion[ctx][c,o,n,t,e,x,t]
+%
+% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
+
+%D \macros
+%D {ordinalnumber, highordinalstr, ordinalstr}
+%D
+%D Efficient general ordinal number converters are sometimes difficult to
+%D implement. Fortunately dates never exceed the number~31.
+
+\permanent\def\highordinalstr#1{\high{\notsmallcapped{#1}}}
+\permanent\def\ordinalstr #1{\notsmallcapped{#1}}
+\permanent\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}}
+\permanent\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}}
+
+\permanent\def\verbosenumber#1{\clf_verbose\numexpr#1\relax{\currentlanguage}}
+\permanent\def\VerboseNumber#1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}}}
+
+%D As longs as symbols are linked to levels or numbers, we can also use the
+%D conversion mechanism, but in for instance the itemization macros, we prefer
+%D symbols because they can more easier be (partially) redefined. Symbols are
+%D implemented in another module.
+
+\permanent\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}}
+\permanent\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}}
+
+\defineconversion [] [\numbers] % the default conversion
+\defineconversion [\v!empty] [\gobbleoneargument]
+\defineconversion [\v!none] [\numbers]
+\defineconversion [\s!default] [\numbers]
+
+\defineconversion [month] [\monthlong]
+\defineconversion [month:mnem] [\monthshort]
+
+\defineconversion [\v!character] [\character]
+\defineconversion [\v!Character] [\Character]
+
+\defineconversion [\v!characters] [\characters]
+\defineconversion [\v!Characters] [\Characters]
+
+\defineconversion [a] [\alphabeticnumerals]
+\defineconversion [A] [\Alphabeticnumerals]
+\defineconversion [AK] [\smallcappedcharacters]
+\defineconversion [KA] [\smallcappedcharacters]
+
+\defineconversion [\v!alphabetic] [\alphabeticnumerals]
+\defineconversion [\v!Alphabetic] [\Alphabeticnumerals]
+
+\defineconversion [\v!number] [\numbers]
+\defineconversion [\v!numbers] [\numbers]
+\defineconversion [\v!Numbers] [\Numbers]
+\defineconversion [\v!mediaeval] [\mediaeval]
+
+\defineconversion [\v!word] [\verbosenumber]
+\defineconversion [\v!words] [\verbosenumber]
+
+\defineconversion [\v!Word] [\VerboseNumber]
+\defineconversion [\v!Words] [\VerboseNumber]
+
+\defineconversion[\v!ordinal] [\ordinalnumber]
+\defineconversion[\v!Ordinal] [\Ordinalnumber]
+
+\defineconversion [n] [\numbers]
+\defineconversion [N] [\Numbers]
+\defineconversion [m] [\mediaeval]
+\defineconversion [o] [\oldstylenumerals]
+\defineconversion [O] [\oldstylenumerals]
+\defineconversion [or] [\oldstyleromannumerals]
+
+\defineconversion [\v!romannumerals] [\romannumerals]
+\defineconversion [\v!Romannumerals] [\Romannumerals]
+
+\defineconversion [i] [\romannumerals]
+\defineconversion [I] [\Romannumerals]
+\defineconversion [r] [\romannumerals]
+\defineconversion [R] [\Romannumerals]
+
+\defineconversion [KR] [\smallcappedromannumerals]
+\defineconversion [RK] [\smallcappedromannumerals]
+
+\defineconversion [\v!greek] [\greeknumerals]
+\defineconversion [\v!Greek] [\Greeknumerals]
+
+\defineconversion [g] [\greeknumerals]
+\defineconversion [G] [\Greeknumerals]
+
+%defineconversion [ñ] [\spanishnumerals]
+%defineconversion [Ñ] [\Spanishnumerals]
+
+\defineconversion [abjadnumerals] [\abjadnumerals]
+\defineconversion [abjadnodotnumerals] [\abjadnodotnumerals]
+\defineconversion [abjadnaivenumerals] [\abjadnaivenumerals]
+
+\defineconversion [hebrewnumerals] [\hebrewnumerals]
+\defineconversion [yiddishnumerals] [\yiddishnumerals]
+
+% users can do: \defineconversion [he] [\hebrewnumerals]
+% users can do: \defineconversion [yi] [\hebrewnumerals]
+
+\defineconversion [thainumerals] [\thainumerals]
+\defineconversion [devanagarinumerals] [\devanagarinumerals]
+\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals]
+\defineconversion [gujaratinumerals] [\gujaratinumerals]
+\defineconversion [tibetannumerals] [\tibetannumerals]
+\defineconversion [greeknumerals] [\greeknumerals]
+\defineconversion [Greeknumerals] [\Greeknumerals]
+\defineconversion [arabicnumerals] [\arabicnumerals]
+\defineconversion [persiannumerals] [\persiannumerals]
+\defineconversion [arabicexnumerals] [\arabicexnumerals]
+\defineconversion [arabicdecimals] [\arabicdecimals]
+\defineconversion [persiandecimals] [\persiandecimals]
+
+\defineconversion [koreannumerals] [\koreannumerals]
+\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while)
+\defineconversion [koreanparenthesisnumerals]
+ [\koreanparenthesisnumerals]
+\defineconversion [koreancirclenumerals] [\koreancirclenumerals]
+
+\defineconversion [kr] [\koreannumerals]
+\defineconversion [kr-p] [\koreanparentnumerals]
+\defineconversion [kr-c] [\koreancirclenumerals]
+
+\defineconversion [chinesenumerals] [\chinesenumerals]
+\defineconversion [chinesecapnumerals] [\chinesecapnumerals]
+\defineconversion [chineseallnumerals] [\chineseallnumerals]
+
+\defineconversion [cn] [\chinesenumerals]
+\defineconversion [cn-c] [\chinesecapnumerals]
+\defineconversion [cn-a] [\chineseallnumerals]
+
+%D Moved from lang-def.mkiv:
+%D
+%D Define these as the general character enumeration when language is Slovenian. If
+%D you feel uncomfortable with this, mail Mojca, since she promised to to take the
+%D heat. Pablo was next to request this. We changed characters to numerals for this
+%D feature. We do need these definitions for mechanisms like itemize that check
+%D for converters.
+
+\permanent\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}}
+\permanent\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}}
+
+\permanent\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}}
+\permanent\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}}
+
+\permanent\def\russiannumerals #1{\clf_alphabetic\numexpr#1\relax{ru}}
+\permanent\def\russianNumerals #1{\clf_Alphabetic\numexpr#1\relax{ru}}
+
+%defineconversion [\s!sl] [character] [\sloveniannumerals]
+%defineconversion [\s!sl] [Character] [\slovenianNumerals]
+%defineconversion [\s!sl] [characters] [\sloveniannumerals]
+%defineconversion [\s!sl] [Characters] [\slovenianNumerals]
+
+\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals]
+\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals]
+
+\defineconversion [\s!sl] [a] [\sloveniannumerals]
+\defineconversion [\s!sl] [A] [\slovenianNumerals]
+\defineconversion [\s!sl] [AK] [\smallcapped\sloveniannumerals]
+\defineconversion [\s!sl] [KA] [\smallcapped\sloveniannumerals]
+
+%defineconversion [\s!es] [character] [\spanishnumerals]
+%defineconversion [\s!es] [Character] [\spanishNumerals]
+%defineconversion [\s!es] [characters] [\spanishnumerals]
+%defineconversion [\s!es] [Characters] [\spanishNumerals]
+
+\defineconversion [\s!es] [alphabetic] [\spanishnumerals]
+\defineconversion [\s!es] [Alphabetic] [\spanishNumerals]
+
+\defineconversion [\s!es] [a] [\spanishnumerals]
+\defineconversion [\s!es] [A] [\spanishNumerals]
+\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals]
+\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals]
+
+%defineconversion [\s!ru] [character] [\russiannumerals]
+%defineconversion [\s!ru] [Character] [\russianNumerals]
+%defineconversion [\s!ru] [characters] [\russiannumerals]
+%defineconversion [\s!ru] [Characters] [\russianNumerals]
+
+\defineconversion [\s!ru] [alphabetic] [\russiannumerals]
+\defineconversion [\s!ru] [Alphabetic] [\russianNumerals]
+
+\defineconversion [\s!ru] [a] [\russiannumerals]
+\defineconversion [\s!ru] [A] [\russianNumerals]
+\defineconversion [\s!ru] [AK] [\smallcapped\russiannumerals]
+\defineconversion [\s!ru] [KA] [\smallcapped\russiannumerals]
+
+\defineconversion [sloveniannumerals] [\sloveniannumerals]
+\defineconversion [slovenianNumerals] [\slovenianNumerals]
+
+\defineconversion [spanishnumerals] [\spanishnumerals]
+\defineconversion [spanishNumerals] [\spanishNumerals]
+
+\defineconversion [russiannumerals] [\russiannumerals]
+\defineconversion [russianNumerals] [\russianNumerals]
+
+%D In case a font has no greek (WS):
+
+\defineconversion [mathgreek]
+ [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ},
+ \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ},
+ \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ},
+ \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}]
+
+%D Handy too (expanded!):
+
+\permanent\def\unihex#1{\clf_unihex\numexpr#1\relax}
+
+%D Symbol sets:
+
+\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo
+
+% \defineconversion
+% [set 0]
+% [{\symbol[bullet]},
+% {\symbol[dash]},
+% {\symbol[star]},
+% {\symbol[triangle]},
+% {\symbol[circle]},
+% {\symbol[medcircle]},
+% {\symbol[bigcircle]},
+% {\symbol[square]},
+% {\symbol[checkmark]}]
+
+% \defineconversion
+% [set 1]
+% [\mathematics{\star},
+% \mathematics{\star\star},
+% \mathematics{\star\star\star},
+% \mathematics{\ddagger},
+% \mathematics{\ddagger\ddagger},
+% \mathematics{\ddagger\ddagger\ddagger},
+% \mathematics{\ast},
+% \mathematics{\ast\ast},
+% \mathematics{\ast\ast\ast}]
+%
+% \defineconversion
+% [set 2]
+% [\mathematics{\ast},
+% \mathematics{\dag},
+% \mathematics{\ddag},
+% \mathematics{\ast\ast},
+% \mathematics{\dag\dag},
+% \mathematics{\ddag\ddag},
+% \mathematics{\ast\ast\ast},
+% \mathematics{\dag\dag\dag},
+% \mathematics{\ddag\ddag\ddag},
+% \mathematics{\ast\ast\ast\ast},
+% \mathematics{\dag\dag\dag\dag},
+% \mathematics{\ddag\ddag\ddag\ddag}]
+%
+% \defineconversion
+% [set 3]
+% [\mathematics{\star},
+% \mathematics{\star\star},
+% \mathematics{\star\star\star},
+% \mathematics{\ddagger},
+% \mathematics{\ddagger\ddagger},
+% \mathematics{\ddagger\ddagger\ddagger},
+% \mathematics{\P},
+% \mathematics{\P\P},
+% \mathematics{\P\P\P},
+% \mathematics{\S},
+% \mathematics{\S\S},
+% \mathematics{\S\S\S},
+% \mathematics{\ast},
+% \mathematics{\ast\ast},
+% \mathematics{\ast\ast\ast}]
+
+\defineconversion
+ [set 0]
+ [\symbol{bullet},
+ \symbol{dash},
+ \symbol{star},
+ \symbol{triangle},
+ \symbol{circle},
+ \symbol{medcircle},
+ \symbol{bigcircle},
+ \symbol{square},
+ \symbol{checkmark}]
+
+\defineconversion
+ [set 1]
+ [\textormathchars{⋆},
+ \textormathchars{⋆⋆},
+ \textormathchars{⋆⋆⋆},
+ \textormathchars{‡},
+ \textormathchars{‡‡},
+ \textormathchars{‡‡‡},
+ \textormathchars{∗},
+ \textormathchars{∗∗},
+ \textormathchars{∗∗∗}]
+
+\defineconversion
+ [set 2]
+ [\textormathchars{∗},
+ \textormathchars{†},
+ \textormathchars{‡},
+ \textormathchars{∗∗},
+ \textormathchars{††},
+ \textormathchars{‡‡},
+ \textormathchars{∗∗∗},
+ \textormathchars{†††},
+ \textormathchars{‡‡‡},
+ \textormathchars{∗∗∗∗},
+ \textormathchars{††††},
+ \textormathchars{‡‡‡‡}]
+
+\defineconversion
+ [set 3]
+ [\textormathchars{⋆},
+ \textormathchars{⋆⋆},
+ \textormathchars{⋆⋆⋆},
+ \textormathchars{‡},
+ \textormathchars{‡‡},
+ \textormathchars{‡‡‡},
+ \textormathchars{¶},
+ \textormathchars{¶¶},
+ \textormathchars{¶¶¶},
+ \textormathchars{§},
+ \textormathchars{§§},
+ \textormathchars{§§§},
+ \textormathchars{∗},
+ \textormathchars{∗∗},
+ \textormathchars{∗∗∗}]
+
+%D Iteration of suggestion by WS on mailinglist 2010.12.22:
+%D
+%D \starttyping
+%D \setupfloatsplitting[conversion=continued]
+%D \stoptyping
+
+\permanent\protected\def\continuednumber#1%
+ {\labeltext{\ifcase#1\or\else\v!continued\fi}}
+
+\defineconversion
+ [\v!continued]
+ [\continuednumber]
+
+%D Taken from x-asciimath (see digits-001.tex for an example):
+
+\let\spaceddigitsmethod \empty % alternative methods : 1 default, 2 and 3 only when > 4
+\let\spaceddigitssymbol \empty % extra splitter symbol : {,}
+\let\spaceddigitsseparator\empty % separator symbol : {\Uchar{"2008}}
+
+\permanent\protected\def\spaceddigits#1%
+ {\clf_spaceddigits
+ method {\spaceddigitsmethod}%
+ symbol {\spaceddigitssymbol}%
+ separator {\spaceddigitsseparator}%
+ data {#1}%
+ \relax}
+
+%D For those who sart counting at zero:
+%D
+%D \starttyping
+%D \defineconversionset [zero] [n,zero] [n]
+%D
+%D \setuphead [sectionconversionset=zero]
+%D
+%D \starttext
+%D \startchapter [title=Introduction]
+%D \startsection [title=First topic] \stopsection
+%D \startsection [title=Second topic] \stopsection
+%D \stopchapter
+%D \stoptext
+%D \stoptyping
+
+\permanent\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax}
+
+\defineconversion [zero] [\zeronumberconversion]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/core-dat.mkiv b/tex/context/base/mkiv/core-dat.mkiv
index 9f4344b99..41a84c3e6 100644
--- a/tex/context/base/mkiv/core-dat.mkiv
+++ b/tex/context/base/mkiv/core-dat.mkiv
@@ -77,9 +77,12 @@
\installcommandhandler \??pagestate {pagestate} \??pagestate
+% \def\syst_pagestates_allocate
+% {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname
+% \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname}
+
\def\syst_pagestates_allocate
- {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname
- \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname}
+ {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname}
\appendtoks
\syst_pagestates_allocate
@@ -91,19 +94,37 @@
\unexpanded\def\setpagestate
{\dodoubleempty\syst_pagestates_set}
+% \def\syst_pagestates_set[#1][#2]%
+% {\begingroup
+% \edef\currentpagestate{#1}%
+% \ifcsname\??pagestatecounter\currentpagestate\endcsname
+% \let\c_syst_pagestate\lastnamedcs
+% \else
+% \syst_pagestates_allocate
+% \fi
+% \global\advance\c_syst_pagestate\plusone
+% \scratchcounter\lastnamedcs
+% \clf_setpagestate
+% name {\currentpagestate}%
+% tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}%
+% delay {\pagestateparameter\c!delay}%
+% \relax
+% \endgroup}
+
\def\syst_pagestates_set[#1][#2]%
{\begingroup
\edef\currentpagestate{#1}%
\ifcsname\??pagestatecounter\currentpagestate\endcsname
- \let\c_syst_pagestate\lastnamedcs
+ \scratchcounter\lastnamedcs
+ \advance\scratchcounter\plusone
\else
+ \scratchcounter\plusone
\syst_pagestates_allocate
\fi
- \global\advance\c_syst_pagestate\plusone
- \scratchcounter\lastnamedcs
+ \global\csname\??pagestatecounter\currentpagestate\endcsname\scratchcounter
\clf_setpagestate
name {\currentpagestate}%
- tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}%
+ tag {\ifsecondargument#2\else\number\scratchcounter\fi}%
delay {\pagestateparameter\c!delay}%
\relax
\endgroup}
diff --git a/tex/context/base/mkiv/core-def.mkiv b/tex/context/base/mkiv/core-def.mkiv
index bb209a8ff..b1300d493 100644
--- a/tex/context/base/mkiv/core-def.mkiv
+++ b/tex/context/base/mkiv/core-def.mkiv
@@ -179,6 +179,6 @@
%D Till we fixed all styles:
-\let\\=\crlf
+\enforced\let\\\crlf % frozen or permanent?
\protect \endinput
diff --git a/tex/context/base/mkiv/core-env.lmt b/tex/context/base/mkiv/core-env.lmt
new file mode 100644
index 000000000..194600c0a
--- /dev/null
+++ b/tex/context/base/mkiv/core-env.lmt
@@ -0,0 +1,193 @@
+if not modules then modules = { } end modules ['core-env'] = {
+ version = 1.001,
+ comment = "companion to core-env.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- maybe this will move to the context name space although the
+-- plurals are unlikely to clash with future tex primitives
+--
+-- if tex.modes['xxxx'] then .... else .... end
+
+local rawset = rawset
+
+local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns
+
+local context = context
+local ctxcore = context.core
+
+local texgetcount = tex.getcount
+local texgetintegervalue = token.get_integer -- todo: in tex namespace
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local setmetatablenewindex = table.setmetatablenewindex
+local setmetatablecall = table.setmetatablecall
+
+local createtoken = token.create
+local isdefined = tokens.isdefined
+
+texmodes = allocate { } tex.modes = texmodes
+texsystemmodes = allocate { } tex.systemmodes = texsystemmodes
+texconstants = allocate { } tex.constants = texconstants
+texconditionals = allocate { } tex.conditionals = texconditionals
+texifs = allocate { } tex.ifs = texifs
+texisdefined = allocate { } tex.isdefined = texisdefined
+
+local modes = { }
+local systemmodes = { }
+
+-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching
+-- at the lua end is not that bad (and we need more anyway)
+
+local cache = tokens.cache
+
+-- we can have a modes cache too
+
+local iftrue = cache["iftrue"].index
+
+local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen
+local countcode = cache["scratchcounter"].command -- tokens.commands.register_int
+local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks
+local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue
+local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue
+local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test
+
+local types = {
+ [dimencode] = "dimen",
+ [countcode] = "count",
+ [tokencode] = "token",
+ [skipcode] = "skip",
+ [muskipcode] = "muskip",
+ -- [attributecode] = "attribute",
+ [conditioncode] = "condition"
+}
+
+setmetatableindex(texmodes, function(t,k)
+ local m = systemmodes[k]
+ if not m then
+ local n = "mode>" .. k
+ m = function() return texgetintegervalue(n) == 1 end
+ rawset(modes,k,m)
+ end
+ return m()
+end)
+
+setmetatableindex(texsystemmodes, function(t,k)
+ local m = systemmodes[k]
+ if not m then
+ local n = "mode>*" .. k
+ m = function() return texgetintegervalue(n) == 1 end
+ rawset(modes,k,m)
+ end
+ return m()
+end)
+
+-- also a call method
+
+context.settrialtypesettingmethod(function() return texsystemmodes.trialtypesetting end)
+
+setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end)
+setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end)
+setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end)
+setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end)
+setmetatablenewindex(texifs, function(t,k) end)
+
+-- if we really need performance we can have a dedicated cache for each
+-- kind of variable
+
+setmetatableindex(texconstants, function(t,k)
+ return cache[k].command == countcode and texgetcount(k) or 0
+end)
+
+setmetatableindex(texconditionals, function(t,k) -- 0 == true
+ return cache[k].command == countcode and texgetcount(k) == 0
+end)
+
+setmetatableindex(texifs, function(t,k)
+ local c = cache[k]
+ print(k)
+ inspect(c)
+ return c.command == conditioncode and c.index == iftrue
+end)
+
+tex.isdefined = isdefined
+
+function tex.isdimen(name)
+ local hit = cache[name]
+ return hit.command == dimencode and hit.index or true
+end
+
+function tex.iscount(name)
+ local hit = cache[name]
+ return hit.command == countcode and hit.index or true
+end
+
+function tex.istoken(name)
+ local hit = cache[name]
+ return hit.command == tokencode and hit.index or true
+end
+
+function tex.isskip(name)
+ local hit = cache[name]
+ return hit.command == skipcode and hit.index or true
+end
+
+function tex.ismuskip(name)
+ local hit = cache[name]
+ return hit.command == muskipcode and hit.index or true
+end
+
+function tex.type(name)
+ return types[cache[name].command] or "macro"
+end
+
+function context.setconditional(name,value)
+ if value then
+ ctxcore.settruevalue(name)
+ else
+ ctxcore.setfalsevalue(name)
+ end
+end
+
+function context.setmode(name,value)
+ if value then
+ ctxcore.setmode(name)
+ else
+ ctxcore.resetmode(name)
+ end
+end
+
+function context.setsystemmode(name,value)
+ if value then
+ ctxcore.setsystemmode(name)
+ else
+ ctxcore.resetsystemmode(name)
+ end
+end
+
+context.modes = texmodes
+context.systemmodes = texsystemmodes
+context.conditionals = texconditionals
+-------.constants = texconstants
+-------.ifs = texifs
+
+local sep = S("), ")
+local str = C((1-sep)^1)
+local tag = P("(") * C((1-S(")" ))^1) * P(")")
+local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")")
+
+local pattern = (
+ P("lua") * tag / ctxcore.luasetup
+ + P("xml") * arg / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments
+ + (P("tex") * tag + str) / ctxcore.texsetup
+ + sep^1
+)^1
+
+interfaces.implement {
+ name = "autosetups",
+ actions = function(str) lpegmatch(pattern,str) end,
+ arguments = "string"
+}
diff --git a/tex/context/base/mkiv/core-env.lua b/tex/context/base/mkiv/core-env.lua
index da10c26f5..1c5165ac8 100644
--- a/tex/context/base/mkiv/core-env.lua
+++ b/tex/context/base/mkiv/core-env.lua
@@ -47,13 +47,12 @@ local cache = tokens.cache
local iftrue = cache["iftrue"].mode
-local dimencode = cache["scratchdimen"] .command -- tokens.commands.assign_dimen
-local countcode = cache["scratchcounter"] .command -- tokens.commands.assign_int
-local tokencode = cache["scratchtoken"] .command -- tokens.commands.assign_toks
-local skipcode = cache["scratchskip"] .command -- tokens.commands.assign_glue
-local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.assign_mu_glue
------ attributecode = cache["scratchattribute"].command -- tokens.commands.assign_attr
-local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test
+local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen
+local countcode = cache["scratchcounter"].command -- tokens.commands.register_int
+local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks
+local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue
+local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue
+local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test
local types = {
[dimencode] = "dimen",
@@ -82,10 +81,6 @@ setmetatableindex(texmodes, function(t,k)
end
end)
-setmetatablenewindex(texmodes, function(t,k)
- report_mode("you cannot set the %s named %a this way","mode",k)
-end)
-
setmetatableindex(texsystemmodes, function(t,k)
local m = systemmodes[k]
if m then
@@ -101,59 +96,38 @@ setmetatableindex(texsystemmodes, function(t,k)
end
end)
-setmetatablenewindex(texsystemmodes, function(t,k)
- report_mode("you cannot set the %s named %a this way","systemmode",k)
-end)
-
-setmetatablenewindex(texconstants, function(t,k)
- report_mode("you cannot set the %s named %a this way","constant",k)
-end)
-
-setmetatablenewindex(texconditionals, function(t,k)
- report_mode("you cannot set the %s named %a this way","conditional",k)
-end)
-
-setmetatablenewindex(texifs, function(t,k)
- -- just ignore
-end)
+do -- we could do the same as in lmtx (use the mode)
-if CONTEXTLMTXMODE > 0 then
+ local trialtypesettingstate = createtoken("trialtypesettingstate").index
+ local texgetcount = tex.getcount
- iftrue = cache["iftrue"].index
-
- -- if we really need performance we can have a dedicated cache for each
- -- kind of variable
-
- setmetatableindex(texconstants, function(t,k)
- return cache[k].command == countcode and texgetcount(k) or 0
+ context.settrialtypesettingmethod(function()
+ return texgetcount(trialtypesettingstate) ~= 0
end)
- setmetatableindex(texconditionals, function(t,k) -- 0 == true
- return cache[k].command == countcode and texgetcount(k) == 0
- end)
-
- setmetatableindex(texifs, function(t,k)
- local c = cache[k]
- print(k)
- inspect(c)
- return c.command == conditioncode and c.index == iftrue
- end)
+end
-else
+setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end)
+setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end)
+setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end)
+setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end)
+setmetatablenewindex(texifs, function(t,k) end)
- setmetatableindex(texconstants, function(t,k)
- return cache[k].mode ~= 0 and texgetcount(k) or 0
- end)
+setmetatablenewindex(texifs, function(t,k)
+ -- just ignore
+end)
- setmetatableindex(texconditionals, function(t,k) -- 0 == true
- return cache[k].mode ~= 0 and texgetcount(k) == 0
- end)
+setmetatableindex(texconstants, function(t,k)
+ return cache[k].mode ~= 0 and texgetcount(k) or 0
+end)
- setmetatableindex(texifs, function(t,k)
- return cache[k].mode == iftrue
- end)
+setmetatableindex(texconditionals, function(t,k) -- 0 == true
+ return cache[k].mode ~= 0 and texgetcount(k) == 0
+end)
-end
+setmetatableindex(texifs, function(t,k)
+ return cache[k].mode == iftrue
+end)
tex.isdefined = isdefined
diff --git a/tex/context/base/mkiv/core-env.mkiv b/tex/context/base/mkiv/core-env.mkiv
index 09de435e7..0f042f815 100644
--- a/tex/context/base/mkiv/core-env.mkiv
+++ b/tex/context/base/mkiv/core-env.mkiv
@@ -17,7 +17,7 @@
\unprotect
-\def\wildcardsymbol{*}
+\ifdefined\wildcardsymbol \else \def\wildcardsymbol{*} \fi
%D Modes:
%D
@@ -104,10 +104,14 @@
% demo: trialtypesetting is a systemmode as well as an if
+\pushoverloadmode
+
\newsystemmode{trialtypesetting}
\expandafter\let\csname\??mode\systemmodeprefix trialtypesetting\endcsname\trialtypesettingstate
+\popoverloadmode
+
\appendtoks
\trialtypesettingstate\enabledmode
\luacopyinputnodes\plusone
@@ -588,13 +592,15 @@
\def\syst_setups_start_loc{\ifsecondargument\expandafter\syst_setups_start_loc_c\else\expandafter\syst_setups_start_loc_d\fi}
\def\syst_setups_start_tex{\ifsecondargument\expandafter\syst_setups_start_tex_c\else\expandafter\syst_setups_start_tex_d\fi}
+% no need for \the\t_syst_setups_lua in the next, now too often
+
\def\syst_setups_start_lua_a{\the\t_syst_setups_lua\dodoubleempty\syst_setups_start_lua} % [ ] delimited
\def\syst_setups_start_xml_a{\the\t_syst_setups_xml\dodoubleempty\syst_setups_start_xml} % [ ] delimited
\def\syst_setups_start_raw_a{\the\t_syst_setups_raw\dodoubleempty\syst_setups_start_raw} % [ ] delimited
\def\syst_setups_start_loc_a{\the\t_syst_setups_loc\dodoubleempty\syst_setups_start_loc} % [ ] delimited
\def\syst_setups_start_tex_a{\the\t_syst_setups_tex\dodoubleempty\syst_setups_start_tex} % [ ] delimited
-% empty preserves inner {} (is removed by the \expandafter{#3})
+% empty preserves inner {} (is removed by the \expandafter{#3}) .. hm, looks old
\def\syst_setups_start_lua_b#1 {\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % space delimited
\def\syst_setups_start_xml_b#1 {\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % space delimited
diff --git a/tex/context/base/mkiv/core-env.mkxl b/tex/context/base/mkiv/core-env.mkxl
new file mode 100644
index 000000000..2d7c22afd
--- /dev/null
+++ b/tex/context/base/mkiv/core-env.mkxl
@@ -0,0 +1,819 @@
+%D \module
+%D [ file=core-env, % was core-new
+%D version=1995.01.01, % wrong
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=New ones,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Core Macros / Environments}
+
+\registerctxluafile{core-env}{autosuffix}
+
+\unprotect
+
+%D Modes:
+%D
+%D \starttyping
+%D \enablemode[screen,paper,bound]
+%D
+%D \doifmodeelse {paper} {this} {that}
+%D \doifmode {paper,screen} {this}
+%D \doifnotmode {paper,bound} {that}
+%D
+%D \startmode [list]
+%D \stopmode
+%D
+%D \startnotmode [list]
+%D \stopnotmode
+%D \stoptyping
+%D
+%D system modes have a * as prefix
+%D
+%D Sometimes, we want to prevent a mode for being set. Think of situations where a
+%D style enables a mode, but an outer level style does not want that. Preventing can
+%D be considered a permanent disabling on forehand.
+
+\aliased\let\systemmodeprefix\wildcardsymbol
+
+% we will have \installcorenamespace{mode} but need some hackery at the lua end then
+
+% TODO: make them mutable, also at the lua end
+
+\installcorenamespace{modestack}
+
+\immutable\def\??mode{mode>} % special namespace, also used at lua end
+
+\permanent\protected\def\newmode #1{\ifcsname \??mode#1\endcsname\else\setmode{#1}\fi}
+\permanent\protected\def\setmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\plusone}
+\permanent\protected\def\resetmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\zerocount}
+\permanent\protected\def\globalsetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\plusone}
+\permanent\protected\def\globalresetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\zerocount}
+
+\permanent\protected\def\newsystemmode #1{\ifcsname \??mode\systemmodeprefix#1\endcsname\else\setsystemmode{#1}\fi}
+\permanent\protected\def\setsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone}
+\permanent\protected\def\resetsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount}
+\permanent\protected\def\globalsetsystemmode #1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone}
+\permanent\protected\def\globalresetsystemmode#1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount}
+
+\expandafter \appendtoks
+ \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\plusone
+ \luacopyinputnodes\plusone
+\to \everysettrialtypesetting
+
+\expandafter \appendtoks
+ \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\zerocount
+ \luacopyinputnodes\zerocount
+\to \everyresettrialtypesetting
+
+\pushoverloadmode \newsystemmode{trialtypesetting} \popoverloadmode
+
+\the\everyresettrialtypesetting
+
+% user ones
+
+\mutable\let\syst_mode_prefix\relax
+
+\protected\def\preventmode{\unprotect\syst_modes_prevent}
+\protected\def\enablemode {\unprotect\syst_modes_enable }
+\protected\def\disablemode{\unprotect\syst_modes_disable}
+
+\protected\def\globalpreventmode{\let\syst_mode_prefix\global\unprotect\syst_modes_prevent}
+\protected\def\globalenablemode {\let\syst_mode_prefix\global\unprotect\syst_modes_enable }
+\protected\def\globaldisablemode{\let\syst_mode_prefix\global\unprotect\syst_modes_disable}
+
+\def\syst_modes_prevent[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_prevent_indeed\let\syst_mode_prefix\relax}
+\def\syst_modes_enable [#1]{\protect\fastprocesscommacommand[#1]\syst_modes_enable_indeed \let\syst_mode_prefix\relax}
+\def\syst_modes_disable[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_disable_indeed\let\syst_mode_prefix\relax}
+
+\def\syst_modes_prevent_indeed#1%
+ {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi
+ \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plustwo}
+
+\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside
+ {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi
+ \ifnum\lastnamedcs=\plustwo\else
+ \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plusone
+ \fi}
+
+\def\syst_modes_disable_indeed#1%
+ {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi
+ \ifnum\lastnamedcs=\plustwo\else
+ \syst_mode_prefix\expandafter\integerdef\lastnamedcs\zerocount
+ \fi}
+
+%D If you do a lot of mode testing, it makes sense to define modes (or disable them
+%D explicitly if unset. This makes testing twice as fast. Often one enables modes
+%D beforehand, in which case \type {\definemode} would reset the mode. The optional
+%D second argument \type {keep} will prevent changing the already set mode but defines
+%D it when undefined.
+
+\permanent\protected\def\definemode
+ {\unprotect
+ \syst_modes_define}
+
+\tolerant\def\syst_modes_define[#1]#*[#2]%
+ {\protect
+ \edef\m_modes_asked{#2}%
+ \fastprocesscommacommand[#1]\syst_modes_define_indeed}
+
+\def\syst_modes_define_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ % already set
+ \else
+ \newmode{#1}%
+ \fi
+ \ifx\m_modes_asked\v!keep
+ % not changes, disabled when undefined
+ \else
+ \expandafter\integerdef\lastnamedcs\ifx\m_modes_asked\v!yes\plusone\else\zerocount\fi
+ \fi}
+
+% handy for mp
+
+\def\booleanmodevalue#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs
+ \s!false
+ \or
+ \s!true
+ \else
+ \s!false
+ \fi
+ \else
+ \s!false
+ \fi}
+
+% check macros
+
+\newconditional\c_checked_mode
+
+% one
+
+\def\syst_modes_check_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs\else
+ \let\syst_modes_check_step\gobbleoneargument
+ \fi
+ \fi}
+
+\def\syst_modes_check_nop#1#2#3%
+ {\let\syst_modes_check_step\syst_modes_check_indeed
+ \fastprocesscommacommand[#3]\syst_modes_check_step
+ \ifx\syst_modes_check_step\gobbleoneargument
+ \expandafter#1%
+ \else
+ \expandafter#2%
+ \fi}
+
+\def\syst_modes_check_yes#1#2#3%
+ {\ifcase\lastnamedcs
+ \expandafter#2%
+ \or
+ \expandafter#1%
+ \else
+ \expandafter#2%
+ \fi}
+
+\def\syst_modes_check_lr#1#2#3%
+ {\ifcsname\??mode#3\endcsname
+ \expandafter\syst_modes_check_yes
+ \else
+ \expandafter\syst_modes_check_nop
+ \fi#1#2{#3}}
+
+\def\syst_modes_check_ss#1#2[#3]%
+ {\ifcsname\??mode#3\endcsname
+ \expandafter\syst_modes_check_yes
+ \else
+ \expandafter\syst_modes_check_nop
+ \fi#1#2{#3}}
+
+% all
+
+\def\syst_modes_check_all_indeed#1%
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\lastnamedcs
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \or
+ % enabled
+ \else
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi
+ \else
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi}
+
+\def\syst_modes_check_all_lr#1#2#3%
+ {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+ \fastprocesscommacommand[#3]\syst_modes_check_all_step
+ \ifx\syst_modes_check_all_step\gobbleoneargument
+ \expandafter#2%
+ \else
+ \expandafter#1%
+ \fi}
+
+\def\syst_modes_check_all_ss#1#2[#3]%
+ {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+ \fastprocesscommacommand[#3]\syst_modes_check_all_step
+ \ifx\syst_modes_check_all_step\gobbleoneargument
+ \expandafter#2%
+ \else
+ \expandafter#1%
+ \fi}
+
+\permanent\protected\def\doifelsemode {\syst_modes_check_lr \firstoftwoarguments \secondoftwoarguments}
+\permanent\protected\def\doifmode {\syst_modes_check_lr \firstofoneargument \gobbleoneargument}
+\permanent\protected\def\doifnotmode {\syst_modes_check_lr \gobbleoneargument \firstofoneargument}
+\permanent\protected\def\startmode {\syst_modes_check_ss \donothing \syst_modes_stop_yes}
+\permanent\protected\def\startnotmode {\syst_modes_check_ss \syst_modes_stop_nop \donothing}
+\permanent\protected\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments \secondoftwoarguments}
+\permanent\protected\def\doifallmodes {\syst_modes_check_all_lr\firstofoneargument \gobbleoneargument}
+\permanent\protected\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument \firstofoneargument}
+\permanent\protected\def\startallmodes {\syst_modes_check_all_ss\donothing \syst_modes_stop_all_yes}
+\permanent\protected\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing}
+
+\aliased\let\doifmodeelse \doifelsemode
+\aliased\let\doifallmodeselse\doifelseallmodes
+
+\permanent\protected\def\stopmode {} % no relax
+\permanent\protected\def\stopnotmode {} % no relax
+\permanent\protected\def\stopallmodes {} % no relax
+\permanent\protected\def\stopnotallmodes{} % no relax
+
+\def\syst_modes_stop_yes #1\stopmode {}
+\def\syst_modes_stop_nop #1\stopnotmode {}
+\def\syst_modes_stop_all_yes#1\stopallmodes {}
+\def\syst_modes_stop_all_nop#1\stopnotallmodes{}
+
+%D Pushing/popping:
+
+\permanent\protected\def\pushmode[#1]{\expandafter\pushmacro\csname\??mode#1\endcsname}
+\permanent\protected\def\popmode [#1]{\expandafter\popmacro \csname\??mode#1\endcsname}
+
+\permanent\protected\def\pushsystemmode#1{\expandafter\pushmacro\csname\??mode\systemmodeprefix#1\endcsname}
+\permanent\protected\def\popsystemmode #1{\expandafter\popmacro \csname\??mode\systemmodeprefix#1\endcsname}
+
+%D Here is a relatively new variant of mode checking:
+%D
+%D \starttyping
+%D \enablemode[two]
+%D
+%D \startmodeset
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodeset
+%D
+%D \startmodeset
+%D [one] {1}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodeset
+%D
+%D \startmodeset
+%D [one] {
+%D \input tufte
+%D }
+%D [two] {
+%D \startmodeset
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodeset
+%D }
+%D [three] {
+%D \input zapf
+%D }
+%D [default] {
+%D \input ward
+%D }
+%D \stopmodeset
+%D \stoptyping
+
+\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped
+
+\permanent\protected\def\startmodeset
+ {\pushmacro\c_syst_modes_set_done
+ \setfalse\c_syst_modes_set_done
+ \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\aliased\let\stopmodeset\relax
+
+\def\syst_modes_set_start[#1]%
+ {\edef\m_mode_case{#1}%
+ \unless\ifx\m_mode_case\s!default
+ \expandafter\syst_modes_set_check
+ \orelse\ifconditional\c_syst_modes_set_done
+ \expandafter\syst_modes_set_quit
+ \else
+ \expandafter\syst_modes_set_yes
+ \fi}
+
+\def\syst_modes_set_check
+ {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case}
+
+\def\syst_modes_set_yes#1%
+ {\settrue\c_syst_modes_set_done
+ #1%
+ \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\def\syst_modes_set_nop#1%
+ {\doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit}
+
+\def\syst_modes_set_quit#-\stopmodeset
+ {\popmacro\c_syst_modes_set_done}
+
+%D Lets now set a mode:
+
+\enablemode[mkiv] \newsystemmode{mkiv} \setsystemmode{mkiv}
+
+%D Setups:
+
+\installcorenamespace{setup} % we can probably get rid of some :'s later on
+
+% \protected\def\startsetups{} % to please dep checker
+% \protected\def\stopsetups {} % to please dep checker
+%
+% \protected\def\setups{\doifelsenextbgroup\syst_setups_a\syst_setups_b} % {..} or [..]
+% \protected\def\setup {\doifelsenextbgroup\syst_setups \syst_setups_c} % {..} or [..]
+%
+% \def\syst_setups_a #1{\processcommacommand[#1]\syst_setups} % {..}
+% \def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..]
+% \def\syst_setups_c[#1]{\syst_setups{#1}} % [..]
+
+\permanent\protected\tolerant\def\setups[#1]#;#2{\processcommacommand[#1#2]\syst_setups} % {..} or [..]
+\permanent\protected\tolerant\def\setup [#1]#;#2{\syst_setups{#1#2}} % {..} or [..]
+
+\letvalue{\??setup:\??empty}\gobbleoneargument
+
+\def\syst_setups#1% the grid option will be extended to other main modes
+ {\csname\??setup
+ \ifgridsnapping
+ \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\??empty\fi\fi
+ \else
+ :\ifcsname\??setup:#1\endcsname#1\else\??empty\fi
+ \fi
+ \endcsname\empty} % takes one argument
+
+% no checking and we assume it being defined:
+
+\def\fastsetup #1{\csname\??setup:#1\endcsname\empty}
+\def\fastsetupwithargument #1{\csname\??setup:#1\endcsname} % swapped per 2015-08-30
+\def\fastsetupwithargumentswapped#1#2{\csname\??setup:#2\endcsname{#1}}% swapped per 2015-09-05
+
+% the next one is meant for \c!setups situations, hence the check for
+% a shortcut
+
+\let\m_syst_setups_asked\empty
+
+\def\doprocesslocalsetups#1% sort of public, fast local variant
+ {\edef\m_syst_setups_asked{#1}%
+ \ifx\m_syst_setups_asked\empty\else
+ \expandafter\syst_setups_process_local
+ \fi}
+
+\protected\def\usesetupsparameter#1%
+ {\edef\m_syst_setups_asked{#1\c!setups}%
+ \ifx\m_syst_setups_asked\empty\else
+ \expandafter\syst_setups_process_local
+ \fi}
+
+% setups=S1
+% setups=lua(S2)
+% setups=S3
+% setups={S1,lua(S2),xml(test{123}),S3}
+
+\def\syst_setups_process_local
+ {\clf_autosetups{\m_syst_setups_asked}%
+ \relax} % let's prevent lookahead
+
+\def\autosetups#1%
+ {\clf_autosetups{#1}}
+
+\edef\setupwithargument#1% saves a few expansions
+ {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname}
+
+\edef\setupwithargumentswapped#1#2% saves a few expansions (can be \let)
+ {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#2\endcsname#2\noexpand\else\??empty\noexpand\fi\endcsname{#1}}
+
+\let\directsetup\syst_setups
+\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup
+
+\protected\def\doifelsesetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doifsetupselse\doifelsesetups
+
+\protected\def\doifsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\protected\def\doifnotsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+% maybe some day:
+%
+% \protected\def\fastsetupfallback#1#2%
+% {\ifcsname\??setup:#1\endcsname
+% \expandafter\lastnamedcs
+% \else
+% \csname\??setup:#2\expandafter\endcsname
+% \fi}
+%
+% or
+%
+% \protected\def\fastsetupfallback#1#2#3% prefix preferred fallback
+% {\ifcsname\??setup:#1#2\endcsname
+% \expandafter\lastnamedcs
+% \else
+% \csname\??setup:#1#3\expandafter\endcsname
+% \fi}
+
+% \startluasetups oeps
+% context("DONE")
+% a = 1
+% b = 1
+% \stopluasetups
+%
+% \luasetup{oeps}
+%
+% \startsetups xxx
+% ziezo
+% \stopsetups
+%
+% \directsetup{xxx}
+%
+% \startxmlsetups zzz
+% [[#1]]
+% \stopxmlsetups
+%
+% \xmlsetup{123}{zzz}
+%
+% \startbuffer[what]
+% context("DONE")
+% \stopbuffer
+%
+% \startbuffer
+% context("MORE")
+% \stopbuffer
+%
+% \ctxluabuffer[what]
+%
+% \ctxluabuffer
+
+\newtoks\t_syst_setups_tex \appendtoks
+ \catcode\endoflineasciicode \ignorecatcode
+\to \t_syst_setups_tex
+
+\newtoks\t_syst_setups_loc \appendtoks
+ \catcode\endoflineasciicode \ignorecatcode
+\to \t_syst_setups_loc
+
+\newtoks\t_syst_setups_raw \appendtoks
+ % nothing
+\to \t_syst_setups_raw
+
+\newtoks\t_syst_setups_xml \appendtoks
+ \catcode\endoflineasciicode\ignorecatcode
+ \catcode\barasciicode \othercatcode
+\to \t_syst_setups_xml
+
+\newtoks\t_syst_setups_lua \appendtoks
+ \obeylualines
+ \obeyluatokens
+\to \t_syst_setups_lua
+
+% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete.
+
+% \protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_a\syst_setups_start_lua_b} \let\stopluasetups \relax
+% \protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_a\syst_setups_start_xml_b} \let\stopxmlsetups \relax
+% \protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_a\syst_setups_start_raw_b} \let\stoprawsetups \relax
+% \protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_a\syst_setups_start_loc_b} \let\stoplocalsetups\relax
+% \protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_a\syst_setups_start_tex_b} \let\stopsetups \relax
+%
+% \def\syst_setups_start_lua_indeed#1#2#3\stopluasetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+% \def\syst_setups_start_xml_indeed#1#2#3\stopxmlsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+% \def\syst_setups_start_raw_indeed#1#2#3\stoprawsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+% \def\syst_setups_start_loc_indeed#1#2#3\stoplocalsetups{\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+% \def\syst_setups_start_tex_indeed#1#2#3\stopsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}}
+%
+% \def\syst_setups_start_lua{\ifsecondargument\expandafter\syst_setups_start_lua_c\else\expandafter\syst_setups_start_lua_d\fi}
+% \def\syst_setups_start_xml{\ifsecondargument\expandafter\syst_setups_start_xml_c\else\expandafter\syst_setups_start_xml_d\fi}
+% \def\syst_setups_start_raw{\ifsecondargument\expandafter\syst_setups_start_raw_c\else\expandafter\syst_setups_start_raw_d\fi}
+% \def\syst_setups_start_loc{\ifsecondargument\expandafter\syst_setups_start_loc_c\else\expandafter\syst_setups_start_loc_d\fi}
+% \def\syst_setups_start_tex{\ifsecondargument\expandafter\syst_setups_start_tex_c\else\expandafter\syst_setups_start_tex_d\fi}
+%
+% % no need for \the\t_syst_setups_lua in the next, now too often
+%
+% \def\syst_setups_start_lua_a{\the\t_syst_setups_lua\dodoubleempty\syst_setups_start_lua} % [ ] delimited
+% \def\syst_setups_start_xml_a{\the\t_syst_setups_xml\dodoubleempty\syst_setups_start_xml} % [ ] delimited
+% \def\syst_setups_start_raw_a{\the\t_syst_setups_raw\dodoubleempty\syst_setups_start_raw} % [ ] delimited
+% \def\syst_setups_start_loc_a{\the\t_syst_setups_loc\dodoubleempty\syst_setups_start_loc} % [ ] delimited
+% \def\syst_setups_start_tex_a{\the\t_syst_setups_tex\dodoubleempty\syst_setups_start_tex} % [ ] delimited
+%
+% % empty preserves inner {} (is removed by the \expandafter{#3})
+%
+% \def\syst_setups_start_lua_b#1 {\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % space delimited
+% \def\syst_setups_start_xml_b#1 {\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % space delimited
+% \def\syst_setups_start_raw_b#1 {\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % space delimited
+% \def\syst_setups_start_loc_b#1 {\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % space delimited
+% \def\syst_setups_start_tex_b#1 {\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % space delimited
+%
+% \def\syst_setups_start_lua_c[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed{#1}{#2}\empty} % [..] [..]
+% \def\syst_setups_start_xml_c[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed{#1}{#2}\empty} % [..] [..]
+% \def\syst_setups_start_raw_c[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed{#1}{#2}\empty} % [..] [..]
+% \def\syst_setups_start_loc_c[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed{#1}{#2}\empty} % [..] [..]
+% \def\syst_setups_start_tex_c[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed{#1}{#2}\empty} % [..] [..]
+%
+% \def\syst_setups_start_lua_d[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % [..]
+% \def\syst_setups_start_xml_d[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % [..]
+% \def\syst_setups_start_raw_d[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % [..]
+% \def\syst_setups_start_loc_d[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % [..]
+% \def\syst_setups_start_tex_d[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % [..]
+
+\permanent\protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_yes\syst_setups_start_lua_nop} \aliased\let\stopluasetups \relax
+\permanent\protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_yes\syst_setups_start_xml_nop} \aliased\let\stopxmlsetups \relax
+\permanent\protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_yes\syst_setups_start_raw_nop} \aliased\let\stoprawsetups \relax
+\permanent\protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_yes\syst_setups_start_loc_nop} \aliased\let\stoplocalsetups\relax
+\permanent\protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_yes\syst_setups_start_tex_nop} \aliased\let\stopsetups \relax
+
+\def\syst_setups_start_lua_two#1#2#+\stopluasetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}}
+\def\syst_setups_start_xml_two#1#2#+\stopxmlsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}}
+\def\syst_setups_start_raw_two#1#2#+\stoprawsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}}
+\def\syst_setups_start_loc_two#1#2#+\stoplocalsetups{\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}}
+\def\syst_setups_start_tex_two#1#2#+\stopsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}}
+
+\tolerant\def\syst_setups_start_lua_yes[#1]#*[#2]%
+ {\the\t_syst_setups_lua
+ \ifarguments\expandafter\syst_setups_start_lua_one
+ \or \expandafter\syst_setups_start_lua_one
+ \else \expandafter\syst_setups_start_lua_two
+ \fi{#1}{#2}}
+
+\tolerant\def\syst_setups_start_xml_yes[#1]#*[#2]%
+ {\the\t_syst_setups_xml
+ \ifarguments\expandafter\syst_setups_start_xml_one
+ \or \expandafter\syst_setups_start_xml_one
+ \else \expandafter\syst_setups_start_xml_two
+ \fi{#1}{#2}}
+
+\tolerant\def\syst_setups_start_raw_yes[#1]#*[#2]%
+ {\the\t_syst_setups_raw
+ \ifarguments\expandafter\syst_setups_start_raw_one
+ \or \expandafter\syst_setups_start_raw_one
+ \else \expandafter\syst_setups_start_raw_two
+ \fi{#1}{#2}}
+
+\tolerant\def\syst_setups_start_loc_yes[#1]#*[#2]%
+ {\the\t_syst_setups_loc
+ \ifarguments\expandafter\syst_setups_start_loc_one
+ \or \expandafter\syst_setups_start_loc_one
+ \else \expandafter\syst_setups_start_loc_two
+ \fi{#1}{#2}}
+
+\tolerant\def\syst_setups_start_tex_yes[#1]#*[#2]%
+ {\the\t_syst_setups_tex
+ \ifarguments\expandafter\syst_setups_start_tex_one
+ \or \expandafter\syst_setups_start_tex_one
+ \else \expandafter\syst_setups_start_tex_two
+ \fi{#1}{#2}}
+
+\def\syst_setups_start_lua_nop#1 {\the\t_syst_setups_lua\syst_setups_start_lua_two{}{#1}} % space delimited
+\def\syst_setups_start_xml_nop#1 {\the\t_syst_setups_xml\syst_setups_start_xml_two{}{#1}} % space delimited
+\def\syst_setups_start_raw_nop#1 {\the\t_syst_setups_raw\syst_setups_start_raw_two{}{#1}} % space delimited
+\def\syst_setups_start_loc_nop#1 {\the\t_syst_setups_loc\syst_setups_start_loc_two{}{#1}} % space delimited
+\def\syst_setups_start_tex_nop#1 {\the\t_syst_setups_tex\syst_setups_start_tex_two{}{#1}} % space delimited
+
+\def\syst_setups_start_lua_one#1#2{\syst_setups_start_lua_two{}{#1}} % [..]
+\def\syst_setups_start_xml_one#1#2{\syst_setups_start_xml_two{}{#1}} % [..]
+\def\syst_setups_start_raw_one#1#2{\syst_setups_start_raw_two{}{#1}} % [..]
+\def\syst_setups_start_loc_one#1#2{\syst_setups_start_loc_two{}{#1}} % [..]
+\def\syst_setups_start_tex_one#1#2{\syst_setups_start_tex_two{}{#1}} % [..]
+
+\def\luasetup#1{\ctxlua{\syst_setups{#1}}}
+
+%D System setups:
+
+\let\systemsetupsprefix\wildcardsymbol
+
+\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}}
+
+\protected\def\resetsetups[#1]% see x-fo for usage
+ {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname
+ \dodoglobal\undefinevalue{\??setup\ifgridsnapping\v!grid\fi:#1}%
+ \else
+ \dodoglobal\undefinevalue{\??setup:#1}%
+ \fi}
+
+\protected\def\copysetups
+ {\dodoubleargument\syst_setups_copy}
+
+\def\syst_setups_copy[#1][#2]%
+ {\ifcsname\??setup:#2\endcsname
+ \expandafter\let\csname\??setup:#1\expandafter\endcsname\lastnamedcs
+ \fi}
+
+\protected\def\showsetupsdefinition[#1]%
+ {\showvalue{\??setup:#1}} % temp hack for debugging
+
+%D \macros
+%D {setvariables,getvariable,getvariabledefault}
+%D
+%D \starttyping
+%D \setvariables[xx][title=]
+%D \setvariables[xx][title=test test]
+%D \setvariables[xx][title=test $x=1$ test] % fatal error reported
+%D \setvariables[xx][title=test {$x=1$} test]
+%D \setvariables[xx][title] % fatal error reported
+%D \setvariables[xx][titletitel=e]
+%D \stoptyping
+
+\installcorenamespace{variables}
+
+\permanent\protected\def\setvariables {\syst_variables_set[\getrawparameters ]}
+\permanent\protected\def\setevariables{\syst_variables_set[\getraweparameters]}
+\permanent\protected\def\setgvariables{\syst_variables_set[\getrawgparameters]}
+\permanent\protected\def\setxvariables{\syst_variables_set[\getrawxparameters]}
+
+% \protected\def\globalsetvariables % obsolete
+% {\dotripleargument\syst_variables_set[\globalgetrawparameters]}
+
+\tolerant\def\syst_variables_set[#1]#*[#2]#*[#3]% tricky, test on s-pre-60
+ {\doifelse{#2}\currentvariableclass
+ {#1[\??variables#2:][#3]}%
+ {\pushmacro\currentvariableclass
+ \def\currentvariableclass{#2}%
+ \getvariable{#2}\s!reset
+ #1[\??variables#2:][#3]%
+ \getvariable{#2}\s!set
+ \popmacro\currentvariableclass}}
+
+\permanent\protected\def\setvariable #1#2#3{\expandafter\def \csname\??variables#1:#2\endcsname{#3}}
+\permanent\protected\def\setevariable#1#2#3{\expandafter\edef\csname\??variables#1:#2\endcsname{#3}}
+\permanent\protected\def\setgvariable#1#2#3{\expandafter\gdef\csname\??variables#1:#2\endcsname{#3}}
+\permanent\protected\def\setxvariable#1#2#3{\expandafter\xdef\csname\??variables#1:#2\endcsname{#3}}
+
+\permanent \def\getvariable #1#2{\begincsname\??variables#1:#2\endcsname}
+\permanent\protected\def\showvariable#1#2{\showvalue{\begincsname\??variables#1:#2\endcsname}}
+
+\let\currentvariableclass\empty
+
+%D \macros
+%D {checkvariables}
+%D
+%D I'll probably forget that this on exists.
+
+\let\m_syst_variables_temp\empty
+
+\permanent\tolerant\def\checkvariables[#1]#*[#2]%
+ {\dogetparameters\syst_variables_check_value[#1][#2]}
+
+\def\syst_variables_check_value#1#2#3%
+ {\ifcsname\??variables#1:#2\endcsname
+ \edef\m_syst_variables_temp{\lastnamedcs}%
+ \ifx\m_syst_variables_temp\empty
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
+ \fi
+ \else
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
+ \fi}
+
+%D \macros
+%D {doifelsevariable,doifvariable,doifnotvariable}
+%D
+%D A few trivial macros:
+
+\permanent\protected\def\doifelsevariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\aliased\let\doifvariableelse\doifelsevariable
+
+\permanent\protected\def\doifvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\permanent\protected\def\doifnotvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D A few more (we could use a public test variable so that we only need to expand
+%D once, assuming expandable variables):
+
+\letvalue{\??variables:}\empty
+
+\permanent\protected\def\doifelseemptyvariable#1#2%
+ {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\aliased\let\doifemptyvariableelse\doifelseemptyvariable
+
+\permanent\protected\def\doifemptyvariable#1#2%
+ {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\permanent\protected\def\doifnotemptyvariable#1#2%
+ {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
+ \ifx\m_syst_string_one\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\permanent\def\getvariabledefault#1#2% #3% can be command
+ {\ifcsname\??variables#1:#2\endcsname
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\permanent\tolerant\protected\def\setupenv[#1]%
+ {\syst_variables_set[\getrawparameters][\s!environment][#1]}
+
+\permanent\protected\def\doifelseenv{\doifelsevariable \s!environment}
+\permanent\protected\def\doifenv {\doifvariable \s!environment}
+\permanent\protected\def\doifnotenv {\doifnotvariable \s!environment}
+\permanent \def\env {\getvariable \s!environment}
+\permanent \def\envvar {\getvariabledefault\s!environment}
+
+\aliased\let\doifenvelse\doifelseenv
+
+%D \macros
+%D {defineselector,setupselector,select,directselect}
+%D
+%D \starttyping
+%D \defineselector[caption][max=2,n=2]
+%D
+%D \start
+%D \setupselector[caption][n=1]
+%D \placelist[figure][criterium=all]
+%D \stop
+%D
+%D \starttext
+%D \placefigure
+%D {\select{caption}{zapf}{\input zapf \relax}}
+%D {}
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{selector}
+
+\permanent\tolerant\protected\def\defineselector[#1]#*[#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]}
+\permanent\tolerant\protected\def\setupselector [#1]#*[#2]{\getparameters[\??selector#1][#2]}
+
+\permanent\protected\let\select\directselect % we promote to protected
+
+% \def\directselect#1% expandable
+% {\filterfromnext % maybe add an \expanded
+% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}%
+% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}}
+%
+% this is more efficient when the arguments are used a few times (or passed along):
+
+\permanent\def\directselect#1% expandable
+ {\expandafter\filterfromnext
+ \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname
+ \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}
+
+\letvalue{\??selector\c!max}\plusone % \aliased ?
+\letvalue{\??selector\c!n }\plusone % \aliased ?
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/core-ini.mkiv b/tex/context/base/mkiv/core-ini.mkiv
index c4ab298bf..31ef501d9 100644
--- a/tex/context/base/mkiv/core-ini.mkiv
+++ b/tex/context/base/mkiv/core-ini.mkiv
@@ -191,7 +191,7 @@
%D
%D This boolean can be used to bypass certain initializations.
-\newif\ifproductionrun
+% \newif\ifproductionrun % already defined
\appendtoks
\productionruntrue
diff --git a/tex/context/base/mkiv/driv-shp.lmt b/tex/context/base/mkiv/driv-shp.lmt
index c117405ba..0d3bddda4 100644
--- a/tex/context/base/mkiv/driv-shp.lmt
+++ b/tex/context/base/mkiv/driv-shp.lmt
@@ -44,6 +44,7 @@ local getdata = nuts.getdata
local getreplace = nuts.getreplace
local setreplace = nuts.setreplace
local getfont = nuts.getfont
+local getkerndimension = nuts.getkerndimension
local setdirection = nuts.setdirection
local setfield = nuts.setfield
@@ -68,7 +69,6 @@ local parameters = fonthashes.parameters
local nodecodes = nodes.nodecodes
local whatsitcodes = nodes.whatsitcodes
-local leadercodes = nodes.leadercodes
local gluecodes = nodes.gluecodes
local dircodes = nodes.dircodes
local dirvalues = nodes.dirvalues
@@ -92,10 +92,10 @@ local whatsit_code = nodecodes.whatsit
----- penalty_code = nodecodes.penalty
----- boundary_code = nodecodes.boundary
-local leaders_code = leadercodes.leaders
-local cleaders_code = leadercodes.cleaders
-local xleaders_code = leadercodes.xleaders
-local gleaders_code = leadercodes.gleaders
+local leaders_code = gluecodes.leaders
+local cleaders_code = gluecodes.cleaders
+local xleaders_code = gluecodes.xleaders
+local gleaders_code = gluecodes.gleaders
local spaceskip_code = gluecodes.spaceskip
@@ -586,7 +586,7 @@ local hlist_out, vlist_out do
-- current = getlist(this_box)
-- end
- -- we can encounter localpar, boundary and penalty nodes but a special
+ -- we can encounter par, boundary and penalty nodes but a special
-- iterator over content nodes won't save much
for current, id, subtype in nextnode, current do
if id == glyph_code then
@@ -775,6 +775,8 @@ local hlist_out, vlist_out do
end
cur_h = cur_h + width
elseif id == kern_code then
+ -- we can use getkerndimension(current) but then we get rounded values so for
+ -- now we calculate ourselves
local kern, factor = getkern(current,true)
if kern ~= 0 then
if factor ~= 0 then
@@ -893,7 +895,7 @@ local hlist_out, vlist_out do
setlink(current,replace)
setreplace(current)
end
- -- elseif id == localpar_code and start_of_par(current) then
+ -- elseif id == par_code and start_of_par(current) then
-- local pardir = getdirection(current) or lefttoright_code
-- if pardir == righttoleft_code then
-- end
diff --git a/tex/context/base/mkiv/enco-ini.mkiv b/tex/context/base/mkiv/enco-ini.mkiv
index f78643975..e4343ba2d 100644
--- a/tex/context/base/mkiv/enco-ini.mkiv
+++ b/tex/context/base/mkiv/enco-ini.mkiv
@@ -314,7 +314,7 @@
% left-overs (some day in private unicode space, so that we can roundtrip)
\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}}
-\unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
+%unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
\unexpanded\def\schwagrave {\buildtextgrave\schwa}
\chardef\textcontrolspace"2423
diff --git a/tex/context/base/mkiv/enco-ini.mkxl b/tex/context/base/mkiv/enco-ini.mkxl
new file mode 100644
index 000000000..609aa28da
--- /dev/null
+++ b/tex/context/base/mkiv/enco-ini.mkxl
@@ -0,0 +1,570 @@
+%D \module
+%D [ file=enco-ini,
+%D version=2007.02.19, % 2000.12.27, % 1998.12.03,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is stripped down version of th eoriginal enco-ini.tex file. For more details
+%D you might want to study the \MKII\ file but since \LUATEX\ is unicode inside we
+%D need less code.
+
+%D Much in here will disappear in \LMTX\ because we assume proper \UNICODE\ usage.
+
+% When dealing with characters we have four cases to take into account when moving
+% from mkii to mkiv:
+
+% 1. <byte 200> => ref to slot 200 in current font
+% 2. \char 200 => ref to slot 200 in current font
+% 3. <active 200> => can (e.g.) map to another slot in current font
+% 4. \namedglyph => can map to some slot in some font
+
+% Using case 2 for special characters is doomed to fail because we are not going
+% to intercept these on the fly as happens automatically with traditional font
+% encoding handling. We could do that in a node pass but it's not worth the effort
+% because we seldom use this case in a document source.
+
+% We can consider using utf as internal format for mkii. The main reason for not
+% doing this before was that it was slow. On the other hand, it would make dealing
+% with utility files easier. However, we've now kind of frozen mkii.
+
+\writestatus{loading}{ConTeXt Encoding Macros / Initialization}
+
+\unprotect
+
+%D Obsolete (but sometimes used in styles)
+
+\let\defaultencoding\s!default
+
+%D \macros
+%D {defineaccent, definecharacter, definecommand}
+%D
+%D Some of these are used at the \LUA\ end!
+
+\installcorenamespace{accents}
+
+\permanent\protected\def\defineaccent#1 #2 #3 %
+ {\dodefineaccentcommand{#1}%
+ \dodefineaccent{#1}{#2}{#3}}
+
+\permanent\protected\def\dodefineaccentcommand#1%
+ {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}}
+
+\permanent\protected\def\dodefineaccent#1#2#3% no spaces, used low level
+ {\setvalue{\??accents\string#1\string#2\empty}{#3}}
+
+% the following dirty trick is needed to catch \asciimath{\^{1/5}log}:
+
+\permanent\protected\def\dohandleaccent#1#2% expandable because we want them in the tuc file
+ {\csname\??accents
+ \ifcsname\??accents\string#1#2\empty\endcsname
+ \string#1#2\empty
+ \orelse\ifcsname\??accents\string#1\string#2\empty\endcsname
+ \string#1\string#2\empty
+ \else
+ \endcsname#2\csname\??accents % very dirty trick: ignore accent but keep char
+ \fi
+ \endcsname}
+
+\immutable\letvalue{\??accents}\empty
+
+\permanent\protected\def\dodefinecommand#1#2%
+ {\frozen\setuvalue{\string#1}{#2}} % not permanent as these are kind of obsolete
+
+\permanent\protected\def\definecharacter#1 #2 %
+ {\doifelsenumber{\string#2}
+ {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax}
+ {\setuvalue{\string#1}{#2}}}
+
+\permanent\protected\def\definecommand#1 #2 %
+ {\setuvalue{\string#1}{#2}}
+
+%D \macros
+%D {everyuppercase, everylowercase, everysanitize}
+
+\newtoks \everyuppercase
+\newtoks \everylowercase
+\newtoks \everysanitize
+
+%D Accent handling (try to avoid this):
+
+% \buildtextaccent\greekdasia\greekalphamacron
+% \buildtextaccent\textacute q
+
+%D We can use offsets in \LMTX\ but even that makes n o sense because we have
+%D a virtual feature already in \MKIV.
+
+%D We define them frozen so that we can overload them.
+
+\newbox\b_enco_accent
+
+\permanent\protected\def\buildmathaccent#1%
+ {\mathaccent#1 }
+
+\permanent\protected\def\buildtextaccent#1#2% we could do all at the lua end
+ {\dontleavehmode\begingroup % but that's no fun (yet)
+ \setbox\scratchboxone\hbox{#1}% accent
+ \setbox\scratchboxtwo\hbox{#2}% character
+ \scratchheight\dimexpr\ht\scratchboxtwo-\ht\scratchboxone\relax
+ \scratchdepth \dimexpr\dp\scratchboxtwo-\dp\scratchboxone\relax
+ \scratchwidth \wd\scratchboxtwo
+ \hbox to \wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi\bgroup
+ \hss\box\scratchboxtwo\hss
+ \hskip-\scratchwidth
+ \hss
+ \ifdim\ht\scratchboxone>\exheight
+ % top accent
+ \raise\dimexpr\scratchheight+\exheight/3\relax
+ \else
+ \lower-\dimexpr\scratchdepth+\exheight/3\relax
+ \fi
+ \box\scratchboxone
+ \hss
+ \egroup
+ \endgroup}
+
+\permanent\protected\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode % why this align mess
+ \vtop
+ {\forgetall
+ \baselineskip\zeropoint
+ \lineskip#1%
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \lineskiplimit\zeropoint
+ \setbox0\hbox{#4}%
+ \halign
+ {##\crcr\hbox{#5}\crcr
+ \hidewidth
+ \hskip#2\wd0
+ \hskip-#3\slantperpoint % in plain 1ex * dimenless value
+ \vpack to .2\exheight{\box0\vss}\hidewidth
+ \crcr}}}
+
+\permanent\protected\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}}
+\permanent\protected\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}}
+\permanent\protected\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}}
+\permanent\protected\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}}
+\permanent\protected\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}}
+
+\aliased\let\d\buildtextbottomdot
+
+\permanent\protected\def\topaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode
+ \bgroup
+ \setbox0\hbox{#4}%
+ \setbox2\hbox{#5}%
+ \hbox to \wd2 \bgroup
+ \hss\copy2\hss
+ \hskip-\wd2
+ \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss
+ \egroup
+ \egroup}
+
+\permanent\protected\def\buildtextgrave
+ {\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
+
+\permanent\protected\def\definemathaccent#1 #2%
+ {\setvalue{#1}{\mathaccent#2 }}
+
+%D Math (will move):
+
+\definemathaccent acute \mathacute
+\definemathaccent grave \mathgrave
+\definemathaccent ddot \mathddot
+\definemathaccent tilde \mathtilde
+\definemathaccent bar \mathbar
+\definemathaccent breve \mathbreve
+\definemathaccent check \mathcheck
+\definemathaccent hat \mathhat
+\definemathaccent vec \mathvec
+\definemathaccent dot \mathdot
+%definemathaccent widetilde \mathwidetilde
+%definemathaccent widehat \mathwidehat
+
+% from enco-def:
+
+% \aliased\let\i\dotlessi
+% \aliased\let\j\dotlessj
+
+% \aliased\let\P\paragraphmark \aliased\let\textP\paragraphmark % obsolete (surfaced in bibliographic files)
+% \aliased\let\S\sectionmark \aliased\let\textS\sectionmark % obsolete (surfaced in bibliographic files)
+
+\permanent\def\eszett {ß} \permanent\def\Eszett {SS} \permanent\def\Ssharp{SS}
+\permanent\def\lslash {ł} \permanent\def\Lslash {Ł}
+\permanent\def\dslash {đ} \permanent\def\Dslash {Đ}
+%permanent\def\oslash {ø} %permanent\def\Oslash {Ø} % clashes with math: use \Ostroke
+\permanent\def\dcroat {đ} \permanent\def\Dcroat {Đ}
+\permanent\def\kcedilla{ķ} \permanent\def\Kcedilla{Ķ}
+\permanent\def\lcedilla{ļ} \permanent\def\Lcedilla{Ļ}
+\permanent\def\ncedilla{ņ} \permanent\def\Ncedilla{Ņ}
+\permanent\def\rcedilla{ŗ} \permanent\def\Rcedilla{Ŗ}
+\permanent\def\aumlaut {ä} \permanent\def\Aumlaut {Ä}
+\permanent\def\eumlaut {ë} \permanent\def\Eumlaut {Ë}
+\permanent\def\iumlaut {ï} \permanent\def\Iumlaut {Ï}
+\permanent\def\oumlaut {ö} \permanent\def\Oumlaut {Ö}
+\permanent\def\uumlaut {ü} \permanent\def\Uumlaut {Ü}
+
+% from enco-com:
+
+% \aliased\let\AE\AEligature \aliased\let\ae\aeligature
+% \aliased\let\OE\OEligature \aliased\let\oe\oeligature
+% \aliased\let\IJ\IJligature \aliased\let\ij\ijligature
+% \aliased\let\AA\textAngstrom \aliased\let\aa\aring
+% \aliased\let\CC\Ccedilla \aliased\let\cc\ccedilla
+% \aliased\let\L \Lslash \aliased\let\l \lslash
+% \aliased\let\O \Oslash \aliased\let\o \oslash
+% \aliased\let\SZ\Eszett \aliased\let\sz\eszett % \aliased\let\SS\Ssharp
+
+% for old times sake (obsolete)
+
+\def\textflorin{ƒ} \def\florin {ƒ}
+\def\pound {£} \def\sterling{£}
+\def\promille {‰} \def\permille{‰}
+
+% tex specific
+
+\pushoverloadmode
+
+%D Was missing:
+
+\permanent\protected\def\ampersand{\mathortext\mathampersand\textampersand}
+
+
+\ifdefined\textpercent
+ \permanent\let\percent \textpercent
+ \permanent\let\procent \textpercent
+ %\permanent\let\ampersand \textampersand
+ \permanent\let\dollar \textdollar
+ \permanent\let\hash \texthash
+\else
+ \permanent\def\percent {\textpercent}
+ \permanent\def\procent {\textpercent}
+ %\permanent\def\ampersand {\textampersand}
+ \permanent\def\dollar {\textdollar}
+ \permanent\def\hash {\texthash}
+\fi
+
+\popoverloadmode
+
+% from enco-mis:
+
+\permanent\protected\def\fakepercent
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}}
+
+\permanent\protected\def\fakeperthousand
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}}
+
+\permanent\protected\def\fakepermine
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox
+ {\mathematics{+}}%
+ \hbox to \wd\scratchbox
+ {\hss
+ \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}%
+ \hss}%
+ \egroup}
+
+\def\permine{\fakepermine}
+
+% some more: what with freezing here?
+
+\ifdefined\softhyphen \else
+ \aliased\let\softhyphen\explicitdiscretionary
+\fi
+
+\def\hyphen {\softhyphen}
+\def\compoundwordmark {\hyphen}
+\def\cwm {\hyphen}
+\def\nonbreakinghyphen{\hyphen}
+\def\breakinghyphen {\hyphen\prewordbreak}
+
+% quotes
+
+\def\lowerleftsingleninequote {\quotesinglebase}
+\def\lowerleftdoubleninequote {\quotedblbase}
+\def\lowerrightsingleninequote {\quotesinglebase}
+\def\lowerrightdoubleninequote {\quotedblbase}
+
+\def\upperleftsingleninequote {\quoteright}
+\def\upperleftdoubleninequote {\quotedblright}
+\def\upperrightsingleninequote {\quoteright}
+\def\upperrightdoubleninequote {\quotedblright}
+
+\def\upperleftsinglesixquote {\quoteleft}
+\def\upperleftdoublesixquote {\quotedblleft}
+\def\upperrightsinglesixquote {\quoteleft}
+\def\upperrightdoublesixquote {\quotedblleft}
+
+\def\leftsubguillemot {\guilsingleleft}
+\def\rightsubguillemot {\guilsingleright}
+
+% left-overs (some day in private unicode space, so that we can roundtrip)
+
+\permanent\protected\def\textblacksquare{\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}}
+%permanent\protected\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
+\permanent\protected\def\schwagrave {\buildtextgrave\schwa}
+
+\chardef\textcontrolspace"2423
+
+\installcorenamespace{controlspace}
+
+% \protected\def\fallbackcontrolspace % beware: non-matching widths
+% {\hbox to \interwordspace{\hss\getglyph{LMTypewriter-Regular}\textcontrolspace\hss}%
+
+\permanent\protected\def\fallbackcontrolspace % beware, current font, we also need to honor color
+ {\hbox to \interwordspace \bgroup
+ \hss
+ \ifcsname\??controlspace\number\interwordspace\endcsname
+ \csname\??controlspace\number\interwordspace\endcsname
+ \else
+ \enco_fast_control_space_define % only regular
+ \fi
+ \textcontrolspace
+ \hss
+ \egroup}
+
+\protected\def\enco_fast_control_space_define
+ {\scratchdimen\interwordspace
+ \definedfont[LMTypewriter-Regular at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody]% see font-sym.mkiv
+ \expandafter\glet\csname\??controlspace\number\scratchdimen\endcsname\lastrawfontcall}
+
+\permanent\protected\def\normalcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \textcontrolspace
+ \else
+ \fallbackcontrolspace
+ \fi}
+
+\let\textvisiblespace\normalcontrolspace
+
+\permanent\protected\def\optionalcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \textcontrolspace
+ \else
+ \asciispacechar % used for export !
+ \fi}
+
+% \protected\def\fastcontrolspace % no glyph resolving after first (use grouped)
+% {\enco_fast_control_space}
+%
+% \def\enco_fast_control_space
+% {\iffontchar\font\textcontrolspace
+% \enco_fast_control_space_nop
+% \else
+% \enco_fast_control_space_yes
+% \fi
+% \enco_fast_control_space}
+%
+% \newbox\b_enco_control_space
+%
+% \def\enco_fast_control_space_nop
+% {\let\enco_fast_control_space\textcontrolspace}
+%
+% \def\enco_fast_control_space_yes
+% {\setbox\b_enco_control_space\fallbackcontrolspace
+% \let\enco_fast_control_space\flushcontrolspacebox}
+%
+% \def\flushcontrolspacebox
+% {\copy\b_enco_control_space}
+
+% a few defaults (\<whatever>{}), we really need the verbose \empty as it will be
+% stringified .. anyhow, we define this at the lua end now but keep it here as a
+% reference
+%
+% \defineaccent ^ {\empty} {\textcircumflex}
+% \defineaccent ` {\empty} {\textgrave}
+% \defineaccent ~ {\empty} {\texttilde}
+% \defineaccent " {\empty} {\textdiaeresis}
+% \defineaccent ' {\empty} {\textacute}
+% \defineaccent . {\empty} {\textdotaccent}
+% \defineaccent = {\empty} {\textmacron}
+% \defineaccent c {\empty} {\textcedilla}
+% \defineaccent H {\empty} {\texthungarumlaut}
+% \defineaccent k {\empty} {\textogonek}
+% \defineaccent r {\empty} {\textring}
+% \defineaccent u {\empty} {\textbreve}
+% \defineaccent v {\empty} {\textcaron}
+
+\clf_defineaccents % one time
+
+%D A smaller and bolder variant, more like the math and monospaced ones.
+
+\permanent\protected\def\fakeunderscore
+ {\relax\ifmmode
+ \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax
+ \else
+ \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}%
+ \fi}
+
+\permanent\protected\def\fakeunderscores{\let\_\fakeunderscore}
+\permanent\protected\def\textunderscores{\let\_\textunderscore}
+
+\textunderscores
+
+\ifdefined\mathunderscore \else \aliased\let\mathunderscore\fakeunderscore \fi
+\ifdefined\textunderscore \else \aliased\let\textunderscore\fakeunderscore \fi
+
+\permanent\protected\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi}
+
+\let\_\normalunderscore
+
+%D To be sorted out:
+
+\pushoverloadmode
+
+\permanent\protected\def\textminus
+ {\char \iffontchar\font"2012 "2012 % figuredash
+ \else\iffontchar\font"2013 "2013 % endash
+ \else\iffontchar\font"2212 "2212 % math minus
+ "002D % hyphen
+ \fi\fi\fi}
+
+\permanent\protected\def\textplus
+ {\char"002B } % plus
+
+\popoverloadmode
+
+%D Moved from core-mis:
+
+\permanent\protected\def\celsius #1{#1\mathematics{^\circ}C}
+\permanent\protected\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
+\permanent\protected\def\fraction#1#2{\mathematics{#1\over#2}}
+
+% \def\periodswidth {.5em}
+% \def\periodsdefault{3} % was 5, but now it's like \unknown
+%
+% \protected\def\periods
+% {\dosingleempty\enco_periods}
+%
+% \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
+% {\dontleavehmode
+% \begingroup
+% \scratchdimen\periodswidth
+% \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen
+% {\leaders\hbox to \scratchdimen{\hss\periodsymbol\hss}\hss}%
+% \endgroup}
+%
+% better for export:
+%
+% \protected\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2
+% {\dontleavehmode
+% \hbox\bgroup
+% \setbox\scratchbox\hbox to \periodswidth{\hss\periodsymbol\hss}%
+% \dorecurse{\iffirstargument#1\else\periodsdefault\fi}{\copy\scratchbox}%
+% \egroup}
+%
+% \protected\def\unknown
+% {\periods\relax} % relax prevents lookahead for []
+%
+% per request:
+
+%D \startbuffer
+%D \startlines
+%D x\periods x
+%D x\periods[10]x
+%D x\periods[n=10,symbol={,}]x
+%D x\periods[n=4,symbol={!!},width=1em]x
+%D x\periods[n=4,symbol={!!},width=fit]x
+%D x\periods[n=4,symbol={!!},width=fit,distance=1em]x
+%D x\unknown x
+%D \stoplines
+%D \stopbuffer
+%D
+%D \typbuffer \getbuffer
+
+\def\periodswidth {.5\emwidth} % downward compatible
+\def\periodsdefault{3} % downward compatible
+
+\installcorenamespace {periods}
+
+\installsetuponlycommandhandler \??periods {periods}
+
+\setupperiods
+ [\c!n=\periodsdefault,
+ \c!width=\periodswidth, % can also be \v!fit
+ \c!distance=.25\emwidth,
+ \c!symbol=.]
+
+\permanent\protected\def\periods
+ {\dontleavehmode
+ \hbox\bgroup
+ \doifelsenextoptional\enco_periods_yes\enco_periods_nop}
+
+\protected\def\enco_periods_yes[#1]%
+ {\doifelseassignment{#1}
+ {\setupcurrentperiods[#1]%
+ \scratchcounter\periodsparameter\c!n}
+ {\doifelsenothing{#1}
+ {\scratchcounter\periodsparameter\c!n}%
+ {\scratchcounter#1}}%
+ \enco_periods_finish}
+
+\protected\def\enco_periods_nop
+ {\scratchcounter\periodsparameter\c!n
+ \enco_periods_finish}
+
+\protected\def\enco_periods_finish
+ {\edef\p_width{\periodsparameter\c!width}%
+ \ifx\p_width\v!fit
+ \enco_periods_finish_fit
+ \else
+ \enco_periods_finish_width
+ \fi
+ \egroup}
+
+\protected\def\enco_periods_finish_width
+ {\setbox\scratchbox\hbox to \p_width
+ {\hss\periodsparameter\c!symbol\hss}%
+ \dorecurse\scratchcounter{\copy\scratchbox}}
+
+\protected\def\enco_periods_finish_fit
+ {\edef\p_symbol{\periodsparameter\c!symbol}%
+ \scratchdistance\periodsparameter\c!distance
+ \hskip\scratchdistance
+ \dorecurse\scratchcounter{\p_symbol\hskip\scratchdistance}}
+
+\permanent\protected\def\unknown
+ {\dontleavehmode
+ \hbox\bgroup
+ \enco_periods_nop}
+
+%D Left-overs:
+
+\appendtoks
+ \enforced\let\buildtextaccent\secondoftwoarguments
+\to \everysimplifycommands
+
+%D A plain one:
+
+% \protected\def\t#1{%
+% \dontleavehmode
+% \begingroup
+% \setbox\scratchboxone\hpack{#1}%
+% \setbox\scratchboxtwo\hpack\bgroup
+% \iffontchar\font"0361\relax
+% \char"0361\relax
+% \else
+% \iffontchar\font"2040\relax\else
+% \the\textfont0
+% \fi
+% \char"2040
+% \fi
+% \egroup
+% \scratchdimenone\wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi
+% \scratchdimentwo\dimexpr-\ht\scratchboxtwo+\ht\scratchboxone+.45\exheight\relax
+% \hpack to \scratchdimenone\bgroup
+% \hpack to \scratchdimenone{\hss\box\scratchboxone\hss}%
+% \hskip -\scratchdimenone
+% \hpack to \scratchdimenone{\hss\raise\scratchdimentwo\box\scratchboxtwo\hss}%
+% \egroup
+% \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/file-ini.mkvi b/tex/context/base/mkiv/file-ini.mkvi
index 5341cc07b..5fa5aa560 100644
--- a/tex/context/base/mkiv/file-ini.mkvi
+++ b/tex/context/base/mkiv/file-ini.mkvi
@@ -115,7 +115,7 @@
%D lines). So, instead of fixing that, we go for a redefinition of \type {\input}.
%D Of course it's better to use \type {\readfile} or \type {\processfile}.
-\unexpanded\def\input{\normalinput}
+% \unexpanded\def\input{\normalinput}
\def\inputgivenfile#name{\normalinput{#name}}
diff --git a/tex/context/base/mkiv/file-job.mkvi b/tex/context/base/mkiv/file-job.mkvi
index db5ac4db1..1f8da6b0c 100644
--- a/tex/context/base/mkiv/file-job.mkvi
+++ b/tex/context/base/mkiv/file-job.mkvi
@@ -133,10 +133,15 @@
\unexpanded\def\starttext {\clf_starttext}
\unexpanded\def\stoptext {\clf_stoptext}
\unexpanded\def\forcequitjob {\clf_forcequitjob}
-\unexpanded\def\end {\clf_forceendjob}
\unexpanded\def\autostarttext{\clf_autostarttext}
\unexpanded\def\autostoptext {\clf_autostoptext}
+\pushoverloadmode
+
+\unexpanded\def\end {\clf_forceendjob}
+
+\popoverloadmode
+
\unexpanded\def\finishjob{\stoptext} % nicer in luatex call commandline
\newtoks\everystartnotext
diff --git a/tex/context/base/mkiv/file-syn.mklx b/tex/context/base/mkiv/file-syn.mklx
new file mode 100644
index 000000000..25f36f742
--- /dev/null
+++ b/tex/context/base/mkiv/file-syn.mklx
@@ -0,0 +1,61 @@
+%D \module
+%D [ file=file-syn, % was core-fil,
+%D version=20110701, % 1997.11.15,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Module Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt File Macros / Synonyms}
+
+\unprotect
+
+\registerctxluafile{file-syn}{}
+
+%D \macros
+%D {definefilesynonym,definefilefallback}
+%D
+%D One of the problems with loading files is that their names can depend on the
+%D interface language. We therefore need a method to define filesynonyms. The actual
+%D synonyms are defined elsewhere, but look like:
+%D
+%D \starttyping
+%D \definefilesynonym [chemic] [chemie]
+%D \definefilesynonym [einheit] [unit]
+%D \definefilesynonym [unit] [unit]
+%D \stoptyping
+%D
+%D So we can say in english:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemic,unit]
+%D \stoptyping
+%D
+%D and in dutch:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemie,unit]
+%D \stoptyping
+
+\permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}}
+\permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}}
+
+%D \macros
+%D {truefilename}
+%D
+%D At the system level such a filename can be called upon by saying:
+%D
+%D \starttyping
+%D \truefilename{filename/filesynonym}
+%D \stoptyping
+%D
+%D The implementation shows that nesting is supported.
+
+\permanent\def\truefilename#1{\clf_truefilename{#1}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index eec967c1c..6c21bc0cc 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -334,9 +334,10 @@ end
-- Watch out: in lmtx the font dimen array is no longer resized automatically.
implement {
- name = "resetnullfont",
- onlyonce = true,
- actions = function()
+ name = "resetnullfont",
+ onlyonce = true,
+ permanent = false,
+ actions = function()
for i=1,7 do
if CONTEXTLMTXMODE > 0 then
font.setfontdimen(0,i,0)
@@ -1020,7 +1021,8 @@ end
local function splitcontext(features) -- presetcontext creates dummy here
local n, sf
- if find(features,",") then
+ -- We can have: "a=yes,b=yes" "a,b" "a" "a=yes" etc.
+ if find(features,"[,=]") then
--
-- from elsewhere (!)
--
diff --git a/tex/context/base/mkiv/font-emp.mklx b/tex/context/base/mkiv/font-emp.mklx
index 8ceee2723..5656c168c 100644
--- a/tex/context/base/mkiv/font-emp.mklx
+++ b/tex/context/base/mkiv/font-emp.mklx
@@ -32,8 +32,8 @@
%D But we prefer:
%D
%D \starttyping
-%D \unexpanded\def\emphasistypeface{\sl}
-%D \unexpanded\def\emphasisboldface{\bs}
+%D \protected\def\emphasistypeface{\sl}
+%D \protected\def\emphasisboldface{\bs}
%D \stoptyping
%D
%D or even better:
@@ -52,33 +52,33 @@
\csname\m_font_emphasized_typeface\endcsname
\fi}
-\unexpanded\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
-\unexpanded\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
+\permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
+\permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
-\unexpanded\def\normalboldface % public
+\permanent\protected\def\normalboldface % public
{\relax
\ifx\fontalternative\s!it\bi\orelse
\ifx\fontalternative\s!sl\bs\else
\bf\fi}
-\unexpanded\def\normalitalicface % public
+\permanent\protected\def\normalitalicface % public
{\relax
\ifx\fontalternative\s!tf\it\orelse
\ifx\fontalternative\s!bf\bi\else
\tf\fi}
-\unexpanded\def\normalslantedface % public
+\permanent\protected\def\normalslantedface % public
{\relax \ifx\fontalternative\s!tf\sl
\orelse\ifx\fontalternative\s!bf\bs
\else \tf\fi}
-\unexpanded\def\normaltypeface % public
+\permanent\protected\def\normaltypeface % public
{\relax
\ifx\fontalternative\s!bi \it \orelse
\ifx\fontalternative\s!bs \sl \else
\tf \fi}
-\unexpanded\def\swaptypeface % public
+\permanent\protected\def\swaptypeface % public
{\relax
\ifx\fontalternative\s!it \tf \orelse
\ifx\fontalternative\s!sl \tf \orelse
@@ -93,14 +93,14 @@
\let\italicface \normalitalicface % public
\let\swapface \swaptypeface % public
-%D To be set with the default body font environment: \type
-%D {em} being \type {slanted} or \type {italic}.
+%D To be set with the default body font environment: \type {em} being \type
+%D {slanted} or \type {italic}.
% maybe a \csname...\fontalternative\endcsname
\newconditional\c_font_emphasis_needed
-\unexpanded\def\em
+\permanent\protected\def\em
{\relax
\ifdim\slantperpoint>\zeropoint
\settrue\c_font_emphasis_needed
@@ -109,15 +109,15 @@
\fi
\font_emphasis_set_emphasis_boldface % new
\ifx\fontalternative\s!it
- \unexpanded\def\emphasistypeface{\it}\tf
+ \enforced\permanent\protected\def\emphasistypeface{\it}\tf
\orelse\ifx\fontalternative\s!sl
- \unexpanded\def\emphasistypeface{\sl}\tf
+ \enforced\permanent\protected\def\emphasistypeface{\sl}\tf
\orelse\ifx\fontalternative\s!bf
\emphasisboldface
\orelse\ifx\fontalternative\s!bs
- \unexpanded\def\emphasisboldface{\bs}\bf
+ \enforced\permanent\protected\def\emphasisboldface{\bs}\bf
\orelse\ifx\fontalternative\s!bi
- \unexpanded\def\emphasisboldface{\bi}\bf
+ \enforced\permanent\protected\def\emphasisboldface{\bi}\bf
\else
\emphasistypeface
\fi
@@ -126,8 +126,8 @@
\fi
\emphasiscorrection}
-%D The next feature was not present in previous versions. It
-%D takes care of \type {\em \bf ...} situations.
+%D The next feature was not present in previous versions. It takes care of \type
+%D {\em \bf ...} situations.
\let\font_emphasis_saved_emphasis_boldface\relax
@@ -136,7 +136,7 @@
\let\font_emphasis_set_emphasis_boldface\relax
\let\bf\font_emphasis_bold_bold}
-\unexpanded\def\font_emphasis_bold_bold
+\protected\def\font_emphasis_bold_bold
{%\relax
\let\bf\relax % new
\ifx\fontalternative\s!it
@@ -154,7 +154,7 @@
\let\italiccorrection=\/ % tex primitive
-\def\emphasiscorrection % public, not in raw alignment groups, else omit problem
+\permanent\protected\def\emphasiscorrection % public, not in raw alignment groups, else omit problem
{\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else
\expandafter\expandafter\expandafter\font_emphasis_look
\fi\fi}
@@ -224,24 +224,24 @@
%D The next emphasis alternatives are for \THANH. They adapt their style as good as
%D possible. These macros are obsolete in \MKIV.
-% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
-% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
-% \unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
-% \unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
-% \unexpanded\def\emph {\groupedcommand{\em}{}}
+% \protected\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+% \protected\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+% \protected\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+% \protected\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+% \protected\def\emph {\groupedcommand{\em}{}}
-\unexpanded\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}}
-\unexpanded\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}}
-\unexpanded\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}}
-\unexpanded\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}
+\protected\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}}
+\protected\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}}
+\protected\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}}
+\protected\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}
-\unexpanded\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf}
-\unexpanded\def\emphit{\triggergroupedcommandcs\font_emphasis_it}
-\unexpanded\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl}
-\unexpanded\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf}
-\unexpanded\def\emph {\triggergroupedcommandcs\em}
+\permanent\protected\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf}
+\permanent\protected\def\emphit{\triggergroupedcommandcs\font_emphasis_it}
+\permanent\protected\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl}
+\permanent\protected\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf}
+\permanent\protected\def\emph {\triggergroupedcommandcs\em}
-\unexpanded\def\emphasized{\bgroup\em\let\nexttoken}
+\permanent\protected\def\emphasized{\bgroup\em\let\nexttoken}
%D \startbuffer
%D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT
diff --git a/tex/context/base/mkiv/font-fea.mklx b/tex/context/base/mkiv/font-fea.mklx
new file mode 100644
index 000000000..010f95500
--- /dev/null
+++ b/tex/context/base/mkiv/font-fea.mklx
@@ -0,0 +1,380 @@
+%D \module
+%D [ file=font-sty,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=features,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Font Macros / Features}
+
+\unprotect
+
+%D Feature management.
+%D
+%D \starttyping
+%D \definefontfeature[smallcaps][smcp=yes,script=latn]
+%D \definefontfeature[smallcaps][SmallCapitals=yes,script=latn]
+%D \definefontfeature[smallcaps][Small Capitals=yes,script=latn]
+%D \definefontfeature[smallcaps][small capitals=yes,script=latn]
+%D \definefontfeature[smallcaps][smallcapitals=yes,script=latn]
+%D
+%D \definedfont[cambria*smallcaps] test
+%D
+%D \starttext
+%D \definefontfeature[basekerned][default][mode=base]
+%D \definefontfeature[nodekerned][default][mode=node]
+%D \definefontfeature[nonekerned][default][mode=base,kern=no]
+%D \setupcolors[state=start]
+%D \startoverlay
+%D {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }}
+%D {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }}
+%D {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }}
+%D \stopoverlay
+%D \stoptext
+%D
+%D \enabletrackers[otf.kerns]
+%D
+%D \definefontfeature[withkern][default][mode=node]
+%D \definefontfeature[nokern] [default][mode=node,kern=no]
+%D \definefontfeature[single] [default][mode=node,cpsp=yes]
+%D \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no]
+%D
+%D {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+%D \stoptyping
+
+% \definefontfeature[slanted] [default][slant=.25]
+% \definefontfeature[stretched][default][stretch=2]
+%
+% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop
+% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop
+%
+% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes]
+% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn]
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular][features=default]
+% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif
+% \stoptypescript
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular*default]
+% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps]
+% \stoptypescript
+%
+% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface]
+%
+% \starttext
+% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl
+% \stoptext
+%
+% \definefontfeature
+% [default-base]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes]
+% \definefontfeature
+% [default-node]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node]
+% \definefontfeature
+% [default-none]
+% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes]
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \definefontfeature[superdefault][default][compose=yes]
+%
+% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683}
+% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683}
+
+\permanent\tolerant\protected\def\definefontfeature[#featureset]#spacer[#parent]#spacer[#settings]%
+ {\clf_definefontfeature{#featureset}{#parent}{#settings}}
+
+\permanent\tolerant\protected\def\adaptfontfeature[#pattern]#spacer[#settings]%
+ {\clf_adaptfontfeature{#pattern}{#settings}}
+
+\permanent\protected\def\fontfeatureslist[#name]#spacer[#separator]% todo: arg voor type
+ {\clf_featurelist{#name}{\detokenize{#separator}}}
+
+\attribute\zerocount\attributeunsetvalue
+
+\glyphdatafield\zerocount
+
+\let\font_dynamic_value\glyphdatafield
+
+% beware: these are global features on top of existing font features
+
+\let\currentfeature \s!current
+\let\m_font_feature_list \s!current
+\let\m_font_feature_asked\empty
+
+\newconstant\c_font_feature_state
+
+% hashing at this end is slower
+
+\permanent\tolerant\protected\def\addfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_add}
+\permanent\tolerant\protected\def\subtractfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_subtract}
+\permanent\tolerant\protected\def\replacefeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_replace}
+\permanent\tolerant\protected\def\resetandaddfeature[#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_reset_add}
+\permanent\tolerant\protected\def\feature [#1]#;#2{\begincsname\??featureshortcut##1#2\endcsname{#1#2}}
+
+% for old times sake
+
+\permanent\protected\def\doaddfeature #1{\edef\m_font_feature_asked{#1}\font_feature_add}
+\permanent\protected\def\dosubtractfeature #1{\edef\m_font_feature_asked{#1}\font_feature_subtract}
+\permanent\protected\def\doreplacefeature #1{\edef\m_font_feature_asked{#1}\font_feature_replace}
+\permanent\protected\def\doresetandaddfeature#1{\edef\m_font_feature_asked{#1}\font_feature_reset_add}
+
+\protected\def\font_feature_add
+ {\ifnum\c_font_feature_state=\plusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_add_indeed
+ \fi
+ \else
+ \font_feature_add_indeed
+ \fi}
+
+\protected\def\font_feature_add_indeed
+ {\clf_addfeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list+\m_font_feature_asked}% also + at the lua end
+ \c_font_feature_state\plusone
+ \let\currentfeature\m_font_feature_asked}
+
+\protected\def\font_feature_subtract
+ {\ifnum\c_font_feature_state=\minusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_subtract_indeed
+ \fi
+ \else
+ \font_feature_subtract_indeed
+ \fi}
+
+\protected\def\font_feature_subtract_indeed
+ {\clf_subtractfeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list-\m_font_feature_asked}% also - at the lua end
+ \c_font_feature_state\minusone
+ \let\currentfeature\m_font_feature_asked}
+
+\protected\def\font_feature_replace
+ {\ifnum\c_font_feature_state=\zerocount
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_replace_indeed
+ \fi
+ \else
+ \font_feature_replace_indeed
+ \fi}
+
+\protected\def\font_feature_replace_indeed
+ {\clf_replacefeature{\m_font_feature_list}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\m_font_feature_list=\m_font_feature_asked}% also = at the lua end
+ \c_font_feature_state\zerocount
+ \let\currentfeature\m_font_feature_asked}
+
+\protected\def\resetfeature
+ {\ifx\currentfeature\s!current \else
+ \font_feature_reset_indeed
+ \fi}
+
+\protected\def\font_feature_reset_indeed
+ {\let\m_font_feature_asked\empty
+ \let\currentfeature \s!current
+ \let\m_font_feature_list \s!current
+ \clf_resetfeature}
+
+\protected\def\revivefeature
+ {\ifx\currentfeature\s!current \else
+ \font_feature_revive_indeed
+ \fi}
+
+\protected\def\font_feature_revive_indeed
+ {\clf_revivefeature{\m_font_feature_list}}
+
+\protected\def\font_feature_reset_add
+ {\ifnum\c_font_feature_state=\plusone
+ \ifx\m_font_feature_asked\currentfeature\else
+ \font_feature_reset_add_indeed
+ \fi
+ \else
+ \font_feature_reset_add_indeed
+ \fi}
+
+\protected\def\font_feature_reset_add_indeed
+ {\clf_addfeature{\s!current}{\m_font_feature_asked}%
+ \edef\m_font_feature_list{\s!current+\m_font_feature_asked}% also + at the lua end
+ \c_font_feature_state\plusone
+ \let\currentfeature\m_font_feature_asked}
+
+\installcorenamespace{featureshortcut}
+
+\letvalue{\??featureshortcut +}\addfeature
+\letvalue{\??featureshortcut -}\subtractfeature
+\letvalue{\??featureshortcut =}\replacefeature
+\letvalue{\??featureshortcut !}\resetandaddfeature
+\letvalue{\??featureshortcut >}\revivefeature
+\letvalue{\??featureshortcut <}\resetfeature
+
+\letvalue{\??featureshortcut\v!more }\addfeature % add set to previous set and combine with font set
+\letvalue{\??featureshortcut\v!less }\subtractfeature % subtract set from previous set and combine with font set
+\letvalue{\??featureshortcut\v!new }\replacefeature % replace font set
+\letvalue{\??featureshortcut\v!reset }\resetfeature % forget sets and revert to font set
+\letvalue{\??featureshortcut\v!default}\revivefeature % make sure the current set is used on top of the font set
+\letvalue{\??featureshortcut\v!old }\revivefeature
+\letvalue{\??featureshortcut\v!local }\resetandaddfeature
+\letvalue{\??featureshortcut\s!unknown}\empty
+
+% experimental bonus:
+
+% \protected\def\addfflanguage
+% {\ifnum\c_font_feature_state=\plusone
+% \ifx\currentlanguage\currentfeature\else
+% \font_feature_add_language_indeed
+% \fi
+% \else
+% \font_feature_add_language_indeed
+% \fi}
+%
+% \protected\def\font_feature_add_language_indeed
+% {\clf_addfeature{\m_font_feature_list}{\currentlanguage}%
+% \edef\m_font_feature_list{\m_font_feature_list+\currentlanguage}% also + at the lua end
+% \c_font_feature_state\plusone
+% \let\currentfeature\currentlanguage}
+%
+% some 3% slower:
+
+% \protected\def\addfflanguage
+% {\let\m_font_feature_asked\currentlanguage
+% \font_feature_add}
+
+\let\m_font_feature_language\currentlanguage
+
+\permanent\protected\def\addfflanguage
+ {\ifx\currentlanguage\m_font_feature_language\else
+ \let\m_font_feature_language\currentlanguage
+ \let\m_font_feature_asked \currentlanguage
+ \font_feature_add
+ \fi}
+
+% just for old times sake:
+
+\permanent\protected\def\featureattribute#feature%
+ {\clf_featureattribute{#feature}}
+
+\permanent\protected\def\setfontfeature#feature%
+ {\edef\currentfeature{#feature}%
+ \let\m_font_feature_list\currentfeature
+ \clf_setfontfeature{\currentfeature}}
+
+\let\resetfontfeature\resetfeature
+
+% these are obsolete (don't use them any longer)
+
+% \let\addfontfeaturetoset \font_feature_add_nop
+% \let\subtractfontfeaturefromset \font_feature_subtract_nop
+% \let\addfontfeaturetofont \font_feature_add_nop
+% \let\subtractfontfeaturefromfont\font_feature_subtract_nop
+
+% also old, maybe some day a comptability module
+
+\let\setff\setfontfeature
+\let\addfs\doaddfeature
+\let\subfs\dosubtractfeature
+\let\addff\doaddfeature
+\let\subff\dosubtractfeature
+
+%D \macros
+%D {os}
+%D
+%D In good old \TEX, the old style numerals were often taken
+%D from the math fonts. No longer.
+
+\definefontfeature
+ [just-os]
+ [mode=node,onum=yes]
+
+%frozen\protected\def\sc{\setfontfeature{smallcaps}}
+\permanent\protected\def\os{\setfontfeature{just-os}}
+
+% \doifelsecurrentfonthasfeature{smcp}{YES}{NO}
+% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
+% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
+
+\permanent\def\doifelsecurrentfonthasfeature#feature{\clf_doifelsecurrentfonthasfeature{#feature}} % expandable
+\permanent\def\doifelsefontfeature #feature{\clf_doifelsefontfeature {#feature}} % expandable
+\permanent\def\doifunknownfontfeature #feature{\clf_doifunknownfontfeature {#feature}} % expandable
+
+\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature
+\let\doiffontfeatureelse \doifelsefontfeature
+
+% new:
+
+\clf_registerlanguagefeatures
+
+% also new
+
+\permanent\protected\def\useaddfontfeatureparameter#namespace% faster local variant
+ {\edef\m_font_feature_asked{#namespace\c!features}%
+ \ifx\m_font_feature_asked\empty\else
+ \font_feature_add
+ \fi}
+
+% let's put this here:
+
+\permanent\protected\def\slashedzero
+ {\dontleavehmode
+ \begingroup
+ %\addff{zero}
+ \doaddfeature{zero}%
+ 0%
+ \endgroup}
+
+% not nice but maybe handy
+
+% \starttyping
+% \blockligatures[fi,ff] \blockligatures[fl]
+%
+% \definefontfeature[default:b][default][blockligatures=yes]
+%
+% \setupbodyfont[pagella] \showfontkerns
+%
+% \definedfont[Serif*default:b]
+%
+% \startTEXpage[offset=1em]
+% fi ff fl
+% \stopTEXpage
+% \stoptyping
+
+\permanent\protected\def\blockligatures[#1]{\clf_blockligatures{#1}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-fil.mklx b/tex/context/base/mkiv/font-fil.mklx
index 3bc5d8c26..7f08a9348 100644
--- a/tex/context/base/mkiv/font-fil.mklx
+++ b/tex/context/base/mkiv/font-fil.mklx
@@ -41,26 +41,22 @@
%
% \setupbodyfont[palatino]
-\unexpanded\def\startfontclass
- {\dosingleempty\font_basics_start_font_class}
-
-\def\font_basics_start_font_class[#class]%
+\permanent\protected\tolerant\protected\def\startfontclass[#class]%
{\push_macro_fontclass
\doifelse{#class}\v!each
{\let\fontclass\empty}
{\doifsomething{#class}{\def\fontclass{#class}}}}
-\unexpanded\def\stopfontclass
+\permanent\protected\def\stopfontclass
{\pop_macro_fontclass}
-\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
+\permanent\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
%D \macros
%D {definefontsynonym, doifelsefontsynonym,
%D expandfontsynonym, truefontname, truefontdata}
%D
-%D While looking for fonts, fontsynonyms are used for accessing
-%D the files!
+%D While looking for fonts, fontsynonyms are used for accessing the files!
%D
%D \starttyping
%D \definefontsynonym[Serif][Lucida-Bright]
@@ -75,7 +71,7 @@
\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
\edef\nullfontname {\fontname\nullfont}
-\unexpanded\def\definefontsynonym[#name]#crap[#file]%
+\permanent\protected\def\definefontsynonym[#name]#spacer[#file]%
{\edef\m_font_name{#name}%
\edef\m_font_file{#file}%
\ifempty\fontclass
@@ -84,15 +80,15 @@
\expandafter\font_basics_define_font_synonym_yes
\fi}
-\unexpanded\def\font_basics_define_font_synonym_nop
+\protected\def\font_basics_define_font_synonym_nop
{\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
\doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil}
-\unexpanded\def\font_basics_define_font_synonym_yes
+\protected\def\font_basics_define_font_synonym_yes
{\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
\doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil}
-\unexpanded\def\edefinefontsynonym[#name]#ignore[#file]%
+\protected\def\edefinefontsynonym[#name]#spacer[#file]%
{\edef\m_font_name{#name}%
\edef\m_font_file{#file}%
\ifempty\fontclass
@@ -101,55 +97,22 @@
\expandafter\font_basics_define_font_synonym_yes_expanded
\fi}
-\unexpanded\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]%
+\protected\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]%
{\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
\normalexpanded{\font_basics_define_font_synonym_nop_opt[#spec]}}
-\unexpanded\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]%
+\protected\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]%
{\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
\normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}}
-% \unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]%
-% {\let\p_features \undefined
-% \let\p_fallbacks \undefined
-% \let\p_goodies \undefined
-% \let\p_designsize\undefined
-% \expandafter\font_basics_get_font_parameter_nop#specification,]=,}
-%
-% \unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]%
-% {\let\p_features \undefined
-% \let\p_fallbacks \undefined
-% \let\p_goodies \undefined
-% \let\p_designsize\undefined
-% \expandafter\font_basics_get_font_parameter_yes#specification,]=,}
-%
-% % todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that
-% % can be default then: \let\mathsizesuffix\relax .. i need to play with it first
-%
-% \def\font_basics_get_font_parameter_nop#key=#value,%
-% {\if]#key%
-% \font_basics_get_font_parameter_nop_finish
-% \else
-% \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
-% \expandafter\font_basics_get_font_parameter_nop
-% \fi}
-%
-% \def\font_basics_get_font_parameter_yes#key=#value,%
-% {\if]#key%
-% \font_basics_get_font_parameter_yes_finish
-% \else
-% \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
-% \expandafter\font_basics_get_font_parameter_yes
-% \fi}
-
-\unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]%
+\protected\def\font_basics_define_font_synonym_nop_opt[#specification]%
{\let\p_features \undefined
\let\p_fallbacks \undefined
\let\p_goodies \undefined
\let\p_designsize\undefined
\expandafter\font_basics_get_font_parameter_nop#specification,\ignorearguments}
-\unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]%
+\protected\def\font_basics_define_font_synonym_yes_opt[#specification]%
{\let\p_features \undefined
\let\p_fallbacks \undefined
\let\p_goodies \undefined
@@ -213,73 +176,23 @@
\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize}
%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
-%
%\defineclassfontsynonym [KopFont] [officina] [SerifBold]
-
-\unexpanded\def\defineclassfontsynonym
- {\dotripleargument\font_basics_define_class_font_synonym}
-
%\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]}
-\def\font_basics_define_class_font_synonym[#tag][#class][#fileortag]% needs testing
+\permanent\tolerant\protected\def\defineclassfontsynonym[#tag]#spacer[#class]#spacer[#fileortag]% needs testing
{\expandafter\normaldef\csname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}%
\font_basics_define_font_synonym_yes_nil}
-\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
-
-\unexpanded\def\setupfontsynonym
- {\dodoubleempty\dosetupfontsynonym}
+\aliased\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
-\def\dosetupfontsynonym[#name][#settings]% not yet supported, will do when needed
+\permanent\tolerant\protected\def\setupfontsynonym[#name]#spacer[#settings]% not yet supported, will do when needed
{}
% todo: replace * by ... less messy with features
-% % no \ifempty here as #1 can be empty
-%
-% \def\truefontname#name%
-% {\expandafter\font_helpers_true_fontname#name*\empty*\relax}
-%
-% \def\font_helpers_true_fontname#name*#first#rest*#crap\relax
-% {\ifcsname\??fontfile\fontclass#name\endcsname
-% \ifx#first\empty
-% \expandafter\truefontname\lastnamedcs
-% \else
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
-% \fi
-% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
-% \ifx#first\empty
-% \expandafter\truefontname\lastnamedcs
-% \else
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
-% \fi
-% \orelse\ifcsname\??fontfile#name\endcsname
-% \ifx#first\empty
-% \expandafter\truefontname\lastnamedcs
-% \else
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
-% \fi
-% \else
-% #name\ifempty#first\else*#first#rest\fi
-% \fi}
-%
-% \def\font_helpers_true_fontname_check#name%
-% {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax}
-%
-% \def\font_helpers_true_fontname_check_indeed#name*#crap\relax
-% {\ifcsname\??fontfile\fontclass#name\endcsname
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs
-% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs
-% \orelse\ifcsname\??fontfile#name\endcsname
-% \expandafter\font_helpers_true_fontname_check\lastnamedcs
-% \else
-% #name%
-% \fi}
-
% no \ifempty here as #1 can be empty
-\def\truefontname#name%
+\permanent\def\truefontname#name%
{\expandafter\font_helpers_true_fontname#name*\empty*\relax}
\def\font_helpers_true_fontname#name*#first#rest*#ignore\relax
@@ -320,31 +233,15 @@
\fi}
% ok when the last lookup is not stripped .. we need to be able to define synonyms for symbols
-%
-% \def\truefontname#name%
-% %{\normalexpanded{\noexpand\font_helpers_true_fontname{\clf_truefontname{#name}}}}
-% {\expandafter\expandafter\expandafter\font_helpers_true_fontname\expandafter\expandafter\expandafter{\clf_truefontname{#name}}}
-%
-% \def\font_helpers_true_fontname#name%
-% {\ifcsname\??fontfile\fontclass#name\endcsname
-% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
-% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
-% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
-% \orelse\ifcsname\??fontfile#name\endcsname
-% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}%
-% \else
-% % \clf_truefontname{#name}%
-% #name% so the last one can have features !
-% \fi}
-
-\def\expandfontsynonym#command#name% one level expansion
+
+\permanent\def\expandfontsynonym#command#name% one level expansion
{\ifcsname\??fontfile\fontclass#name\endcsname
\expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
\orelse\ifcsname\??fontfile\defaultfontclass#2\endcsname
\expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
\fi}
-\def\doifelsefontsynonym#name%
+\permanent\def\doifelsefontsynonym#name%
{\ifcsname\??fontfile\fontclass#name\endcsname
\expandafter\firstoftwoarguments
\orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname
@@ -353,14 +250,14 @@
\expandafter\secondoftwoarguments
\fi}
-\let\doiffontsynonymelse\doifelsefontsynonym
+\aliased\let\doiffontsynonymelse\doifelsefontsynonym
%D \macros
%D {tracedfontname}
%D
%D A goody:
-\def\tracedfontname#name%
+\permanent\def\tracedfontname#name%
{#name\ifcsname\??fontfile\fontclass#name\endcsname
%\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
\expandafter\tracedfontname\lastnamedcs
@@ -379,7 +276,7 @@
\let\fontclass \empty
\let\defaultfontclass\empty
-\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting
+\permanent\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting
{\ifcsname\??fontfile#class#name\endcsname
\fontclassname{#class}{\csname\??fontfile#class#name\endcsname}%
\orelse\ifcsname\??fontfile#name\endcsname
@@ -394,8 +291,8 @@
%D They can inherit them.
% Why these expanded and rscale not ... maybe not worth the trouble (delayed
-% expansion actually would be better i.e. macros in feature specs). Test
-% without pre-expansion.
+% expansion actually would be better i.e. macros in feature specs). Test without
+% pre-expansion.
\def\font_helpers_update_font_class_parameters
{\edef\m_font_class_direction {\begincsname\??fontclass\fontclass\fontstyle\s!direction \endcsname}%
@@ -473,7 +370,7 @@
% we can pack them (don't use \setxvalue!)
-\unexpanded\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction%
+\permanent\protected\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction%
{\letgvalue{\??fontclass\fontclass#style\s!rscale }#rscale%
\letgvalue{\??fontclass\fontclass#style\s!features }#features%
\letgvalue{\??fontclass\fontclass#style\s!fallbacks }#fallbacks%
diff --git a/tex/context/base/mkiv/font-ini.mklx b/tex/context/base/mkiv/font-ini.mklx
index 882f879a2..a9e01e7ec 100644
--- a/tex/context/base/mkiv/font-ini.mklx
+++ b/tex/context/base/mkiv/font-ini.mklx
@@ -12,6 +12,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% todo: frozen tolerant iftok etc
+
% todo: < 3 pt => 3pt
% todo: check where more class usage
% todo: split font-nam (style/alternative/size)
@@ -326,12 +328,12 @@
\newtoks\t_font_tracers_definitions
-\unexpanded\def\tracefontdefinitions
+\permanent\protected\def\tracefontdefinitions
{\the\t_font_tracers_definitions}
%D Some housekeeping macros:
-\unexpanded\def\setfontparameters
+\permanent\protected\def\setfontparameters
{\setfalse\c_font_synchronize
\the\everybodyfont
\settrue\c_font_synchronize}
@@ -340,16 +342,22 @@
\installmacrostack\savedfont
-\unexpanded\def\savefont
- {\edef\savedfont{\the\font}% gives \csname
+% \fontname\font : string
+% \fontid \font : integer
+% \the \font : token (reference to font)
+% \fontspecifiedname : string
+% \the \fontspecifiedsize : dimension
+
+\permanent\protected\def\savefont
+ {\edef\savedfont{\the\font}%
\push_macro_savedfont}
-\unexpanded\def\restorefont
+\permanent\protected\def\restorefont
{\pop_macro_savedfont
\savedfont}
-\unexpanded\def\pushcurrentfont
- {\edef\popcurrentfont
+\permanent\protected\def\pushcurrentfont
+ {\enforced\permanent\protected\edef\popcurrentfont
{\def\noexpand\fontbody {\fontbody}%
\def\noexpand\fontstyle {\fontstyle}%
\def\noexpand\fontalternative{\fontalternative}%
@@ -361,24 +369,20 @@
\let\thedefinedfont\relax % not to be confused with \everydefinefont
-\unexpanded\def\definedfont
- {\doifelsenextoptionalcs\font_basics_defined_font_yes\font_basics_defined_font_nop}
-
-\def\font_basics_defined_font_yes[#specification]%
- {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
- \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
- \thedefinedfont
- \the\everydefinedfont}
-
-\def\font_basics_defined_font_nop
- {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+\permanent\tolerant\protected\def\definedfont[#specification]%
+ {\ifarguments
+ \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \or
+ \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \fi
\thedefinedfont
\the\everydefinedfont}
%D \macros{startfont}
-\unexpanded\def\startfont{\begingroup\definedfont}
-\unexpanded\def\stopfont {\endgroup}
+\permanent\protected\def\startfont{\begingroup\definedfont}
+\permanent\protected\def\stopfont {\endgroup}
%D \macros
%D {everybodyfont,everyglobalbodyfont}
@@ -411,7 +415,7 @@
\installcorenamespace{fontnormalizedbody}
-\def\normalizebodyfontsize#macro#body%
+\protected\def\normalizebodyfontsize#macro#body%
{\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\dimexpr#body\endcsname
\ifx#macro\relax
\normalizebodyfontsize_indeed#macro{#body}%
@@ -424,9 +428,9 @@
\def\thenormalizedbodyfontsize#body%
{\clf_nbfs\dimexpr#body\relax}
-\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
-\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
-\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+\protected\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
+\protected\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+\protected\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
%D \macros
%D {mapfontsize}
@@ -457,11 +461,8 @@
\installcorenamespace{mappedfontsize}
-\unexpanded\def\mapfontsize
- {\dodoubleargument\font_basics_map_fontsize}
-
-\def\font_basics_map_fontsize[#from][#to]%
- {\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}}
+\permanent\tolerant\protected\def\mapfontsize[#from]#spacer[#to]%
+ {\ifarguments\or\or\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}\fi}
\def\font_basics_set_mapped_fontsize#from%
{\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname
@@ -555,10 +556,7 @@
\def\font_helpers_register_size #size{\expandafter\let\csname\??fontsizeknown #size\endcsname\empty}
\def\font_helpers_register_alternative#alternative{\expandafter\let\csname\??fontalternativeknown#alternative\endcsname\empty}
-\unexpanded\def\definefontstyle
- {\dodoubleargument\font_basics_define_fontstyle}
-
-\def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ...
+\permanent\protected\def\definefontstyle[#commands]#spacer[#style]% style: rm ss tt ...
{\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
\font_helpers_register_style{#style}%
\toksapp\t_font_style_commands{\m_font_style_command{#style}}%
@@ -569,21 +567,21 @@
{\setvalue{\??fontshortstyle#command}{#style}%
\setvalue{\??fontstyle #command}{\csname#style\endcsname}}
-\unexpanded\def\definefontsize[#size]%
+\permanent\protected\def\definefontsize[#size]%
{\ifcsname\??fontsizeknown#size\endcsname \else
\font_helpers_register_size{#size}%
\toksapp\t_font_size_commands{\m_font_size_command{#size}}%
\fi
\font_helpers_check_fontname_combinations}
-\unexpanded\def\definefontalternative[#alternative]%
+\permanent\protected\def\definefontalternative[#alternative]%
{\ifcsname\??fontalternativeknown#alternative\endcsname \else
\font_helpers_register_alternative{#alternative}%
\toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}%
\fi
\font_helpers_check_fontname_combinations}
-\unexpanded\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb)
+\protected\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb)
{\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s}
\def\font_helpers_check_fontname_combinations_s#style%
@@ -692,7 +690,7 @@
\newconditional\c_font_body_scale
\newfraction \f_font_body_scale
-\unexpanded\def\font_helpers_low_level_define#specification#csname%
+\protected\def\font_helpers_low_level_define#specification#csname%
{% we can now set more at the lua end
\glet\somefontname\defaultfontfile
\let\somefontsize\empty
@@ -895,7 +893,7 @@
%D
%D The implementation looks as follows:
-\unexpanded\def\definefont % [name][spec][1.6 | line=10pt | setup_id]
+\protected\def\definefont % [name][spec][1.6 | line=10pt | setup_id]
{\dotripleempty\font_basics_define_font}
\def\font_basics_define_font
@@ -925,22 +923,15 @@
%D Beware, in the frozen variants no settings are supported yet, but that might happen
%D some day.
-\unexpanded\def\definefrozenfont
- {\dotripleempty\font_basics_define_frozen_font}
-
-% \def\font_basics_define_frozen_font[#name][#specification][#settings]%
-% {\begingroup
-% \font_basics_define_font[#name][#specification][#settings]%
-% \csname#name\endcsname
-% \expandafter\expandafter\expandafter\endgroup\expandafter\let\csname#name\endcsname\lastrawfontcall}
-
-\def\font_basics_define_frozen_font[#name][#specification][#settings]%
- {\begingroup
- \font_basics_define_font[#name][#specification][#settings]%
- \csname#name\endcsname
- \glet\lastglobalrawfontcall\lastrawfontcall
- \endgroup
- \expandafter\let\csname#name\endcsname\lastglobalrawfontcall}
+\permanent\tolerant\protected\def\definefrozenfont[#name]#spacer[#specification]#spacer[#settings]%
+ {\ifparameter#name\or
+ \begingroup
+ \font_basics_define_font[#name][#specification][#settings]%
+ \csname#name\endcsname
+ \glet\lastglobalrawfontcall\lastrawfontcall
+ \endgroup
+ \expandafter\let\csname#name\endcsname\lastglobalrawfontcall
+ \fi}
%D The instance namespace protection makes the switch local so that we can redefine a
%D logical name and/or change the size in between.
@@ -976,7 +967,7 @@
\the\everyfontswitch
\let\v_font_identifier_basic\v_font_identifier_basic_saved}
-\unexpanded\def\font_helpers_trigger#identifier% make a traced variant
+\protected\def\font_helpers_trigger#identifier% make a traced variant
{\edef\lastfontidentifier{#identifier}%
\ifcsname\v_font_identifier_class\endcsname
% \writestatus{fonts}{trigger: reusing \v_font_identifier_class}%
@@ -1192,11 +1183,6 @@
\lastnamedcs\dimexpr#body\relax\fi % factor
\relax}
-\unexpanded\def\definebodyfontenvironment
- {\dotripleempty\font_basics_define_body_font_environment}
-
-\let\setupbodyfontenvironment\definebodyfontenvironment
-
\installcorenamespace{fontenvironmentknown}
\def\font_helpers_register_environment#class#body%
@@ -1205,6 +1191,9 @@
\newmacro\m_font_body
\newmacro\m_font_body_normalized
+\permanent\protected\def\definebodyfontenvironment % todo
+ {\dotripleempty\font_basics_define_body_font_environment}
+
\def\font_basics_define_body_font_environment
{\ifthirdargument
\singleexpandafter\font_basics_define_body_font_environment_class
@@ -1214,11 +1203,13 @@
\expandafter\font_basics_define_body_font_environment_unset
\fi}
+\let\setupbodyfontenvironment\definebodyfontenvironment
+
%D First we handle the class specific case. Beware: you can change values before
%D a bodyfont is loaded but changing them afterwards can be sort of tricky as
%D values are not consulted afterwards.
-\def\processbodyfontenvironmentlist#1% no \unexpanded as then we cannot use it in alignments
+\def\processbodyfontenvironmentlist#1% no \protected as then we cannot use it in alignments (still?)
{\clf_processbodyfontsizes{\strippedcsname#1}}
\def\bodyfontenvironmentlist
@@ -1371,17 +1362,22 @@
% [class] [10pt,11pt] [settings] == [name] [rm] [settings]
% [class] [10pt,11pt] [name] == [10pt,11pt] [rm] [name]
-\unexpanded\def\definebodyfont
- {\doquadrupleempty\font_basics_define_body_font}
-
-\def\font_basics_define_body_font[#1][#2][#3][#4]%
- {\iffourthargument
+\permanent\tolerant\protected\def\definebodyfont[#1]#*[#2]#*[#3]#*[#4]%
+ {\ifarguments
+ \or
+ \font_basics_define_body_font[#1][\s!rm][]%
+ \or
+ \font_basics_define_body_font[#1][\s!rm][#2]%
+ \or
+ \font_basics_define_body_font[#1][#2][#3]%
+ \or
\processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}%
- \else
- \font_basics_define_body_font_class_known[#1][#2][#3]%
\fi}
-\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
+\protected\def\font_basics_define_body_font[#whatever]%
+ {\doifelsenumber{#whatever}\font_basics_define_body_font_body\font_basics_define_body_font_name[#whatever]}
+
+\protected\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
{\push_macro_fontclass
\doifelse{#4}\s!default
{\let\fontclass\empty}
@@ -1389,28 +1385,7 @@
\definebodyfont[#1][#2][#3]%
\pop_macro_fontclass}
-\def\font_basics_define_body_font_class_known
- {\ifthirdargument
- \singleexpandafter\font_basics_define_body_font_a
- \orelse\ifsecondargument
- \expandafter\font_basics_define_body_font_b
- \else
- \expandafter\font_basics_define_body_font_c
- \fi}
-
-\unexpanded\def\font_basics_define_body_font_b[#whatever][#specification][#dummy]% body|identifier defs|identifier
- {\font_basics_define_body_font_a[#whatever][\s!rm][#specification]}
-
-\unexpanded\def\font_basics_define_body_font_c[#whatever][#dummya][#dummyb]% body|identifier
- {\font_basics_define_body_font_a[#whatever][\s!rm][]}
-
-\unexpanded\def\font_basics_define_body_font_a[#whatever]%
- {\doifelsenumber{#whatever}%
- \font_basics_define_body_font_body
- \font_basics_define_body_font_name
- [#whatever]}
-
-\unexpanded\def\font_basics_define_body_font_body[#body][#style][#specification]%
+\protected\def\font_basics_define_body_font_body[#body][#style][#specification]%
{\ifcondition\validassignment{#specification}%
\expandafter\font_basics_define_body_font_body_assignment
\else
@@ -1418,7 +1393,7 @@
\fi
[#body][#style][#specification]}%
-\unexpanded\def\font_basics_define_body_font_name[#name][#style][#specification]%
+\protected\def\font_basics_define_body_font_name[#name][#style][#specification]%
{\ifcondition\validassignment{#specification}%
\expandafter\font_basics_define_body_font_name_assignment
\else
@@ -1426,41 +1401,41 @@
\fi
[#name][#style][#specification]}%
-\unexpanded\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]%
+\protected\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]%
{\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}}
-\unexpanded\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body%
+\protected\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body%
{\normalizebodyfontsize\m_font_asked_body{#body}%
% normally we define quite a lot in advance, i.e global defs
\font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
\processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}}
-\unexpanded\def\font_basics_define_body_font_body_assignment_b#assignments#style%
+\protected\def\font_basics_define_body_font_body_assignment_b#assignments#style%
{\edef\m_font_asked_style{#style}%
\processcommalist[#assignments]\font_basics_define_body_font_defs}
-\unexpanded\def\font_basics_define_body_font_defs
+\protected\def\font_basics_define_body_font_defs
{\ifempty\fontclass
\expandafter\font_basics_define_body_font_defs_nop
\else
\expandafter\font_basics_define_body_font_defs_yes
\fi}
-\unexpanded\def\font_basics_define_body_font_defs_yes_normal#assignment%
+\protected\def\font_basics_define_body_font_defs_yes_normal#assignment%
{\ifx\m_font_asked_style\s!mm
\expandafter\font_basics_define_body_font_yes_mm
\else
\expandafter\font_basics_define_body_font_yes_xx
\fi[#assignment]}
-\unexpanded\def\font_basics_define_body_font_defs_nop_normal#assignment%
+\protected\def\font_basics_define_body_font_defs_nop_normal#assignment%
{\ifx\m_font_asked_style\s!mm
\expandafter\font_basics_define_body_font_nop_mm
\else
\expandafter\font_basics_define_body_font_nop_xx
\fi[#assignment]}
-\unexpanded\def\font_basics_define_body_font_defs_yes_traced#assignment%
+\protected\def\font_basics_define_body_font_defs_yes_traced#assignment%
{\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
\ifx\m_font_asked_style\s!mm
\expandafter\font_basics_define_body_font_yes_mm
@@ -1468,7 +1443,7 @@
\expandafter\font_basics_define_body_font_yes_xx
\fi[#assignment]}
-\unexpanded\def\font_basics_define_body_font_defs_nop_traced#assignment%
+\protected\def\font_basics_define_body_font_defs_nop_traced#assignment%
{\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}%
\ifx\m_font_asked_style\s!mm
\expandafter\font_basics_define_body_font_nop_mm
@@ -1488,29 +1463,29 @@
%D the style and the rest is a size, although in practice one will seldom define the
%D size directly. We might even drop that as it gives faster code.
-\unexpanded\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
+\protected\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local
{\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
\expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined
- \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
\expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined
- \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
\expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined
- \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
-\unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
+\protected\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
{\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
\expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
- \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
+ \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
\expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
- \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
+ \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
\expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
- \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
+ \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
@@ -1519,52 +1494,52 @@
%D Here the rest concerns rl or lr so in this case it is not a size specifier but
%D a directional one.
-\unexpanded\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local
+\protected\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local
{%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
\expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
% \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
% \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
- \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname
{\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\noexpand\font_rscale_mm}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
% \writestatus{fonts}{define \m_asked_style\space nop: \expandafter\meaning\csname\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
-\unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
+\protected\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
{%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
\expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
% \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
% \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
- \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
+ \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
{\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
% \writestatus{fonts}{define \m_asked_style\space yes: \expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}%
-\unexpanded\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]%
+\protected\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]%
{\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}}
-\unexpanded\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body%
+\protected\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body%
{\normalizebodyfontsize\m_font_asked_body{#body}%
\font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !!
\processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}}
-\unexpanded\def\font_basics_define_body_font_body_identifier_b#name#style%
+\protected\def\font_basics_define_body_font_body_identifier_b#name#style%
{\edef\m_font_asked_style{#style}%
%\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}%
\csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking
-\unexpanded\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]%
+\protected\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]%
{\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}}
-\unexpanded\def\font_basics_define_body_font_name_assignment_a#name#assignments#style%
+\protected\def\font_basics_define_body_font_name_assignment_a#name#assignments#style%
{%\writestatus\m!fonts{[#name:#style] => [#assignments]}%
\setevalue{\??fontdefinitions#name:#style}{\font_basics_define_body_font_default{#assignments}}}
-\unexpanded\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]%
+\protected\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]%
{\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}}
-\unexpanded\def\font_basics_define_body_font_name_identifier_a#name#identifier#style%
+\protected\def\font_basics_define_body_font_name_identifier_a#name#identifier#style%
{%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}%
\ifcsname\??fontdefinitions#name:#style\endcsname
\expandafter\let\csname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname
@@ -1577,7 +1552,7 @@
\newconditional\c_font_defining_unknown
\newconditional\c_font_defining_state
-\unexpanded\def\font_helpers_define_unknown_font#body% one level only
+\protected\def\font_helpers_define_unknown_font#body% one level only
{\font_helpers_register_fontbody{#body}% prevents loop, can go
\setfalse\c_font_defining_state
\font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}%
@@ -1615,20 +1590,13 @@
\settrue\c_font_defining_state
\fi}
-% \def\font_helpers_define_unknown_check_relatives#body#relativesize%
-% {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
-% % how \lastnamedcs here
-% \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
-% \settrue\c_font_defining_state
-% \fi}
-
\def\font_helpers_define_unknown_check_relatives#body#relativesize%
{\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else
\expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname
\settrue\c_font_defining_state
\fi}
-\unexpanded\def\font_basics_define_body_font_default#assignments%
+\protected\def\font_basics_define_body_font_default#assignments%
{\font_helpers_check_relative_font_size\m_font_asked_style % still needed here?
\ifcsname\m_font_asked_style\endcsname\else
\normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}%
@@ -1639,7 +1607,7 @@
%D These macros show that quite some definitions take place. Fonts are not loaded
%D yet! This means that at format generation time, no font files are present.
-\unexpanded\def\font_basics_switch_points#body%
+\protected\def\font_basics_switch_points#body%
{\ifcsname\??fontbodyknown#body\endcsname \else
% we need to check the relative sizes for this body
\font_helpers_define_unknown_font{#body}%
@@ -1653,7 +1621,7 @@
\showmessage\m!fonts4{#body}%
\fi}
-\unexpanded\def\font_basics_switch_style#style%
+\protected\def\font_basics_switch_style#style%
{\ifcsname\??fontstyle#style\endcsname
\lastnamedcs
\edef\fontstyle{#style}%
@@ -1702,7 +1670,7 @@
\newmacro\m_font_keyword
-\unexpanded\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
+\protected\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
{\edef\m_font_keyword{#keyword}%
\ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname
\edef\m_font_step{\font_bodyfontvariable\m_font_keyword}%
@@ -1725,7 +1693,7 @@
\def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later
{\let\fontstyle\s!rm}
-\unexpanded\def\font_helpers_set_font_set_font_option_body#method#body#message%
+\protected\def\font_helpers_set_font_set_font_option_body#method#body#message%
{\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls
\ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else
\font_helpers_define_unknown_font\normalizedsetfont
@@ -1754,7 +1722,7 @@
\ifdefined\trycurrentfontclass \else
- \unexpanded\def\trycurrentfontclass#typeface%
+ \protected\def\trycurrentfontclass#typeface%
{\letvalueempty{\??fontclassnop#typeface}}
\fi
@@ -1766,7 +1734,7 @@
%D So far for synchronisation. (We can inline the following macros.)
-\unexpanded\def\setcurrentfont#body#style#alternative#size% not used
+\protected\def\setcurrentfont#body#style#alternative#size% not used
{\edef\fontbody {#body}%
\edef\fontstyle {#style}%
\edef\fontalternative{#alternative}%
@@ -1774,7 +1742,7 @@
\font_helpers_check_big_math_synchronization
\font_helpers_synchronize_font}
-\unexpanded\def\setcurrentfontbody#body% % not used
+\protected\def\setcurrentfontbody#body% % not used
{\edef\fontbody{#body}%
\font_helpers_synchronize_font}
@@ -1784,51 +1752,51 @@
\let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini
\fi
-\unexpanded\def\font_helpers_set_current_font_style#style%
+\protected\def\font_helpers_set_current_font_style#style%
{\edef\fontstyle{#style}%
\font_typescripts_inherit_check\fontstyle
\ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_xsize_alternative#xsize#alternative%
+\protected\def\font_helpers_set_current_xsize_alternative#xsize#alternative%
{\edef\fontface{#xsize}%
\edef\fontalternative{#alternative}%
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_alternative#alternative%
+\protected\def\font_helpers_set_current_font_alternative#alternative%
{\edef\fontalternative{#alternative}%
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_size#size%
+\protected\def\font_helpers_set_current_font_size#size%
{\edef\fontsize{#size}%
\font_helpers_check_big_math_synchronization % double? better in everymath?
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl
+\protected\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl
{\edef\fontstyle {#style}%
\edef\fontalternative{#alternative}%
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_style_size#style#size% \rma
+\protected\def\font_helpers_set_current_font_style_size#style#size% \rma
{\edef\fontstyle{#style}%
\edef\fontsize {#size}%
\font_helpers_check_big_math_synchronization % double? better in everymath?
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
+\protected\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
{\edef\fontalternative{#alternative}%
\edef\fontsize {#size}%
\font_helpers_check_big_math_synchronization % double? better in everymath?
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla
+\protected\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla
{\edef\fontstyle {#style}%
\edef\fontalternative{#alternative}%
\edef\fontsize {#size}%
\font_helpers_check_big_math_synchronization % double? better in everymath?
\font_helpers_synchronize_font}
-\unexpanded\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
+\protected\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
{\ifempty\fontclass
\applyfontstrategies
\else
@@ -2071,7 +2039,9 @@
\let\fontalternative\fontalternative
\font_helpers_synchronize_font}
-\unexpanded\def\tx
+% to freeze or not ...
+
+\protected\def\tx
{\currentxfontsize\plusone
\ifmmode
\scriptstyle
@@ -2082,7 +2052,7 @@
\fi
\let\tx\txx}
-\unexpanded\def\txx
+\protected\def\txx
{\currentxfontsize\plustwo
\ifmmode
\scriptscriptstyle
@@ -2094,7 +2064,7 @@
\let\tx \empty
\let\txx\empty}
-\unexpanded\def\sx
+\protected\def\sx
{\currentxfontsize\plusone
\ifmmode
\scriptstyle
@@ -2104,7 +2074,7 @@
\let\tx\txx
\let\sx\sxx}
-\unexpanded\def\sxx
+\protected\def\sxx
{\currentxfontsize\plustwo
\ifmmode
\scriptscriptstyle
@@ -2116,8 +2086,8 @@
\let\sx \empty
\let\sxx\empty}
-\unexpanded\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me
-\unexpanded\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me
+\permanent\protected\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me
+\permanent\protected\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me
\let\normaltx \tx
\let\normaltxx\txx
@@ -2139,7 +2109,7 @@
\installcorenamespace{fontbodyfaces}
-\unexpanded\def\font_basics_complete_switch#size%
+\protected\def\font_basics_complete_switch#size%
{\bodyfontsize#size\relax
\normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
\expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname
@@ -2205,7 +2175,7 @@
% \newtoks \everysetupbodyfont
% \newtoks \everyswitchtobodyfont
-\unexpanded\def\setupbodyfont
+\permanent\protected\def\setupbodyfont
{\doifelsenextoptionalcs\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop}
\def\font_basics_setupbodyfont_nop
@@ -2225,7 +2195,7 @@
\fi
\the\everysetupbodyfont}}
-\unexpanded\def\font_basics_switchtobodyfont#specification%
+\protected\def\font_basics_switchtobodyfont#specification%
{\edef\m_font_step{\font_bodyfontvariable{#specification}}%
\ifempty\m_font_step
\font_helpers_set_font\zerocount{#specification}%
@@ -2235,10 +2205,10 @@
\the\everybodyfont
\the\everyswitchtobodyfont}
-\unexpanded\def\switchtobodyfont[#specification]% could become an ifx
+\permanent\protected\def\switchtobodyfont[#specification]% could become an ifx
{\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}}
-\unexpanded\def\usebodyfontparameter#1%
+\permanent\protected\def\usebodyfontparameter#1%
{\edef\m_font_bodyfont_asked{#1\c!bodyfont}%
\ifempty\m_font_bodyfont_asked\else
\font_basics_switchtobodyfont\m_font_bodyfont_asked
@@ -2251,7 +2221,7 @@
%D The following alternative is meant for math||to||text switching and will be
%D optimized.
-\unexpanded\def\fastswitchtobodyfont#name%
+\permanent\protected\def\fastswitchtobodyfont#name%
{\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
%\edef\futurebodyfontsize{\csname\??fontenvironments\normalizedbodyfontsize#name\endcsname}%
\edef\futurebodyfontsize{\lastnamedcs}%
@@ -2284,7 +2254,7 @@
%D \stoptext
%D \stoptyping
-\unexpanded\def\usebodyfont[#1]%
+\permanent\protected\def\usebodyfont[#1]%
{\ifempty\fontclass
\setupbodyfont[#1]%
\else
@@ -2292,7 +2262,7 @@
\fullrestoreglobalbodyfont
\fi}
-\unexpanded\def\showbodyfontstate
+\permanent\protected\def\showbodyfontstate
{\dontleavehmode
\start
\infofont
@@ -2320,9 +2290,9 @@
%D
%D This is an expandable command!
-\unexpanded\def\fontchar #character{\clf_fontchar{#character}}
-\unexpanded\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax}
- \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef)
+\permanent\protected\def\fontchar #character{\clf_fontchar{#character}}
+\permanent\protected\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax}
+\permanent \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef)
%D The next auxilliary macro is an alternative to \type {\fontname}.
@@ -2340,7 +2310,7 @@
%D {\sl text \switchstyleonly[sansserif]text}
%D \stoptyping
-\unexpanded\def\switchstyleonly
+\permanent\protected\def\switchstyleonly
{\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg}
\def\font_basics_switch_style_only_arg#name% stupid version
@@ -2363,10 +2333,7 @@
%D
%D We don't support language specific synonyms here.
-\unexpanded\def\definebodyfontswitch
- {\dodoubleargument\font_basics_define_bodyfont_switch}
-
-\def\font_basics_define_bodyfont_switch[#command][#specification]% no longer a commalist (not useful)
+\permanent\tolerant\protected\def\definebodyfontswitch[#command]#spacer[#specification]% no longer a commalist (not useful)
{\setvalue{#command}{\switchtobodyfont[#specification]}}%
%D \macros
@@ -2384,10 +2351,10 @@
\font_basics_switch_points\m_font_step
\font_basics_switch_style \fontstyle}
-\unexpanded\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont}
-\unexpanded\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont}
+\permanent\protected\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont}
+\permanent\protected\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont}
-\unexpanded\def\setmainbodyfont
+\permanent\protected\def\setmainbodyfont
{\font_basics_switch_points\normalizedbodyfontsize
\font_basics_switch_style\fontstyle
\the\everybodyfont
@@ -2409,7 +2376,7 @@
\let\globalfontstyle\s!rm
-\unexpanded\def\fullrestoreglobalbodyfont
+\permanent\protected\def\fullrestoreglobalbodyfont
{\let\fontsize\defaultfontsize
\let\fontbody\defaultfontbody
\let\fontface\defaultfontface
@@ -2423,7 +2390,7 @@
\the\everyglobalbodyfont
\saveinterlinespace}
-\unexpanded\def\partialrestoreglobalbodyfont
+\permanent\protected\def\partialrestoreglobalbodyfont
{\let\fontsize\defaultfontsize
\let\fontbody\defaultfontbody
\let\fontface\defaultfontface
@@ -2434,7 +2401,7 @@
\the\everyglobalbodyfont % indeed needed
\saveinterlinespace}
-\unexpanded\def\restoreglobalbodyfont % ook style etc
+\permanent\protected\def\restoreglobalbodyfont % ook style etc
{\ifx\fontclass\globalfontclass
\ifx\fontstyle\globalfontstyle
\ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
@@ -2466,26 +2433,26 @@
\installcorenamespace{predefinedfont}
-\unexpanded\def\predefinefont[#1]#2[#3]% global !
- {\setugvalue{#1}{\font_basics_predefine{#1}{#3}}}
+\permanent\protected\def\predefinefont[#1]#*[#2]% global !
+ {\setugvalue{#1}{\font_basics_predefine{#1}{#2}}}
-\unexpanded\def\predefinedfont[#1]% global !
+\permanent\protected\def\predefinedfont[#1]% global !
{\ifcsname\??predefinedfont#1\endcsname
\lastnamedcs
\else
\font_basics_predefined{#1}%
\fi}
-\unexpanded\def\font_basics_predefine#1#2%
+\protected\def\font_basics_predefine#1#2%
{\font_basics_defined_font_yes[#2]%
\expandafter\glet\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname}
-\unexpanded\def\font_basics_predefined#1%
+\protected\def\font_basics_predefined#1%
{\font_basics_predefine{\??predefinedfont#1}{#1}}
%D Handy helper:
-\unexpanded\def\savedefinedfont[#1]%
+\permanent\protected\def\savedefinedfont[#1]%
{\bgroup
\definedfont[#1]%
\xdef\saveddefinedfontid {\number\fontid\font}%
@@ -2497,8 +2464,8 @@
%D Ugly helper:
-\unexpanded\def\saverunningstyleandcolor
- {\unexpanded\edef\restorerunningstyleandcolor
+\permanent\protected\def\saverunningstyleandcolor
+ {\enforced\permanent\protected\edef\restorerunningstyleandcolor
{\setfontid \number\fontid\font
\c_attr_colormodel \the\c_attr_colormodel
\c_attr_color \the\c_attr_color
@@ -2515,10 +2482,10 @@
\let\getprivatemathchar \clf_getprivatemathchar % gives back a utf !
\let\getprivateslot \clf_getprivateslot % companion to fonts.helpers.addprivate
-% \unexpanded\def\getprivatemathchar#1%
+% \protected\def\getprivatemathchar#1%
% {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup}
-\def\privatechar % the text variant gets expanded to utf
+\permanent\protected\def\privatechar % the text variant gets expanded to utf
{\ifmmode
\expandafter\getprivatemathchar
\else
@@ -2546,10 +2513,7 @@
%D \stopTEXpage
%D \stoptyping
-\unexpanded\def\definefontcolorpalette
- {\dodoubleargument\font_define_color_palette}
-
-\def\font_define_color_palette[#1][#2]%
+\permanent\tolerant\protected\def\definefontcolorpalette[#1]#*[#2]%
{\clf_definefontcolorpalette{#1}{#2}}
%D \macros
@@ -2557,7 +2521,7 @@
%D
%D A way to add a path at runtime (no need to generate database):
-\unexpanded\def\usefontpath[#1]%
+\permanent\protected\def\usefontpath[#1]%
{\clf_addfontpath{#1}}
\protect \endinput
diff --git a/tex/context/base/mkiv/font-mat.mklx b/tex/context/base/mkiv/font-mat.mklx
index c37b36ed6..8ee5f4043 100644
--- a/tex/context/base/mkiv/font-mat.mklx
+++ b/tex/context/base/mkiv/font-mat.mklx
@@ -40,10 +40,10 @@
\newtoks \t_font_math_strategies
\newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts
-\unexpanded\def\font_helpers_synchronize_math % math stuff in mmode
+\protected\def\font_helpers_synchronize_math % math stuff in mmode
{\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi}
-\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
+\permanent\protected\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
%D The main math font definer. We have removed some optimized code simply because we
%D now always have a fontclass. We could check for fontclass being default or empty
@@ -67,6 +67,8 @@
\newconditional\c_font_bidirectional_mathstrategy % can be default, not that much overhead: \settrue\c_font_bidirectional_mathstrategy
\newconditional\c_font_complete_bold_mathstrategy \settrue\c_font_complete_bold_mathstrategy
+% \frozen ...
+
\def\mathtextsuffix {-text}
\def\mathscriptsuffix {-script}
\def\mathscriptscriptsuffix{-scriptscript}
@@ -343,7 +345,7 @@
\fam\defaultmathfamily % all characters and symbols are in this family
\to \everymathematics
-\unexpanded\def\font_helpers_synchronize_math_family_mr
+\protected\def\font_helpers_synchronize_math_family_mr
{\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy
\ifconditional\c_math_right_to_left
\plustwo
@@ -354,7 +356,7 @@
\zerocount
\fi}
-\unexpanded\def\font_helpers_synchronize_math_family_mb
+\protected\def\font_helpers_synchronize_math_family_mb
{\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy
\ifconditional\c_math_right_to_left
\ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi
@@ -415,7 +417,7 @@
\newconditional\c_math_bold
-\unexpanded\def\mr % math regular
+\protected\def\mr % math regular
{\ifmmode
\font_helpers_synchronize_math_family_mr
\else
@@ -424,7 +426,7 @@
\mathdefault
\setfalse\c_math_bold}
-\unexpanded\def\mb % math bold
+\protected\def\mb % math bold
{\ifmmode
\font_helpers_synchronize_math_family_mb
\else
@@ -462,13 +464,13 @@
\fi
\to \everymathematics
-\unexpanded\def\nobigmath {\synchronizebigmathflag\zerocount}
-\unexpanded\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
-\unexpanded\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
+\protected\def\nobigmath {\synchronizebigmathflag\zerocount}
+\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
+\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
\let\bigmathfontsize\empty
-\unexpanded\def\synchronizebigmath
+\protected\def\synchronizebigmath
{\ifx\bigmathfontsize\fontsize
% already in sync
\else
@@ -476,7 +478,7 @@
\font_helpers_synchronize_math
\fi}
-\unexpanded\def\font_helpers_check_big_math_synchronization
+\protected\def\font_helpers_check_big_math_synchronization
{\ifcase\synchronizebigmathflag
% never
\or
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index bf0aa3ba0..f3cd37f17 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -55,7 +55,7 @@ local disc_code = nodecodes.disc
local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -396,7 +396,7 @@ function step_tracers.codes(i,command,space)
local char, id = isglyph(c)
if char then
showchar(char,id)
- elseif id == dir_code or (id == localpar_code and start_of_par(c)) then
+ elseif id == dir_code or (id == par_code and start_of_par(c)) then
context("[%s]",getdirection(c) or "?")
elseif id == disc_code then
local pre, post, replace = getdisc(c)
diff --git a/tex/context/base/mkiv/font-ocm.lua b/tex/context/base/mkiv/font-ocm.lua
index 131b0ed13..2f6c29e65 100644
--- a/tex/context/base/mkiv/font-ocm.lua
+++ b/tex/context/base/mkiv/font-ocm.lua
@@ -188,7 +188,7 @@ local initializeoverlay do
n = n + 1 ; t[n] = "}"
end
token.set_macro("typethreemacro",concat(t))
- tex.runtoks("typethreetoks")
+ tex.runlocal("typethreetoks")
registertypethreeresource(specification,c,tex.saveboxresource(0,nil,lpdf.collectedresources(),true))
-- registertypethreefont(specification,mainid,lpdf.reference(lpdf.getfontobjnumber(mainid)))
return 0, 0
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index 490f28de6..bb13a4801 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -251,7 +251,7 @@ local glue_code = nodecodes.glue
local disc_code = nodecodes.disc
local math_code = nodecodes.math
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local lefttoright_code = nodes.dirvalues.lefttoright
local righttoleft_code = nodes.dirvalues.righttoleft
@@ -500,9 +500,23 @@ end
-- in the not discfound branch then. We now have skiphash too so we can be more
-- selective if needed (todo).
+-- we can have more granularity here but for now we only do a simple check
+
+local no_left_ligature_code = 1
+local no_right_ligature_code = 2
+local no_left_kern_code = 4
+local no_right_kern_code = 8
+
+local has_glyph_option = node.direct.has_glyph_option or function(n,c)
+ if c == no_left_ligature_code or c == no_right_ligature_code then
+ return getattr(n,a_noligature) == 1
+ else
+ return false
+ end
+end
+
local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfound,hasmarks) -- brr head
- if getattr(start,a_noligature) == 1 then
- -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+ if has_glyph_option(start,no_right_ligature_code) then
return head, start
end
if start == stop and getchar(start) == char then
@@ -902,81 +916,89 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
end
function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection)
- local startchar = getchar(start)
- local format = step.format
- if format == "single" or type(kerns) == "table" then -- the table check can go
- local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %s xy (%p,%p) and wh (%p,%p)",pref(dataset,sequence),gref(startchar),format,dx,dy,w,h)
- end
+ if has_glyph_option(start,no_right_kern_code) then
+ return head, start, false
else
- local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %s %p",pref(dataset,sequence),gref(startchar),format,k)
+ local startchar = getchar(start)
+ local format = step.format
+ if format == "single" or type(kerns) == "table" then -- the table check can go
+ local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %s xy (%p,%p) and wh (%p,%p)",pref(dataset,sequence),gref(startchar),format,dx,dy,w,h)
+ end
+ else
+ local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %s %p",pref(dataset,sequence),gref(startchar),format,k)
+ end
end
+ return head, start, true
end
- return head, start, true
end
function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection)
- local snext = getnext(start)
- if not snext then
+ if has_glyph_option(start,no_right_kern_code) then
return head, start, false
else
- local prev = start
- while snext do
- local nextchar = ischar(snext,currentfont)
- if nextchar then
- if skiphash and skiphash[nextchar] then -- includes marks too when flag
- prev = snext
- snext = getnext(snext)
- else
- local krn = kerns[nextchar]
- if not krn then
- break
- end
- local format = step.format
- if format == "pair" then
- local a = krn[1]
- local b = krn[2]
- if a == true then
- -- zero
- elseif a then -- #a > 0
- local x, y, w, h = setposition(1,start,factor,rlmode,a,injection)
- if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting first of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
- end
+ local snext = getnext(start)
+ if not snext then
+ return head, start, false
+ else
+ local prev = start
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if nextchar then
+ if skiphash and skiphash[nextchar] then -- includes marks too when flag
+ prev = snext
+ snext = getnext(snext)
+ else
+ local krn = kerns[nextchar]
+ if not krn then
+ break
end
- if b == true then
- -- zero
- start = snext -- cf spec
- elseif b then -- #b > 0
- local x, y, w, h = setposition(2,snext,factor,rlmode,b,injection)
+ local format = step.format
+ if format == "pair" then
+ local a = krn[1]
+ local b = krn[2]
+ if a == true then
+ -- zero
+ elseif a then -- #a > 0
+ local x, y, w, h = setposition(1,start,factor,rlmode,a,injection)
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ end
+ end
+ if b == true then
+ -- zero
+ start = snext -- cf spec
+ elseif b then -- #b > 0
+ local x, y, w, h = setposition(2,snext,factor,rlmode,b,injection)
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ end
+ start = snext -- cf spec
+ elseif forcepairadvance then
+ start = snext -- for testing, not cf spec
+ end
+ return head, start, true
+ elseif krn ~= 0 then
+ local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn,injection)
if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting second of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+ logprocess("%s: inserting %s %p between %s and %s as %s",pref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar),injection or "injections")
end
- start = snext -- cf spec
- elseif forcepairadvance then
- start = snext -- for testing, not cf spec
- end
- return head, start, true
- elseif krn ~= 0 then
- local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting %s %p between %s and %s as %s",pref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar),injection or "injections")
+ return head, start, true
+ else -- can't happen
+ break
end
- return head, start, true
- else -- can't happen
- break
end
+ else
+ break
end
- else
- break
end
+ return head, start, false
end
- return head, start, false
end
end
@@ -1505,92 +1527,96 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup
end
function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex)
- local mapping = currentlookup.mapping
- if mapping == nil then
- mapping = getmapping(dataset,sequence,currentlookup)
- end
- if mapping then
- local startchar = getchar(start)
- local kerns = mapping[startchar]
- if kerns then
- local format = currentlookup.format
- if format == "single" then
- local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns) -- currentlookup.flags ?
- if trace_kerns then
- logprocess("%s: shifting single %s by %s (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),format,dx,dy,w,h)
- end
- else -- needs checking .. maybe no kerns format for single
- local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %s %p",cref(dataset,sequence),gref(startchar),format,k)
+ if has_glyph_option(start,no_right_kern_code) then
+ local mapping = currentlookup.mapping
+ if mapping == nil then
+ mapping = getmapping(dataset,sequence,currentlookup)
+ end
+ if mapping then
+ local startchar = getchar(start)
+ local kerns = mapping[startchar]
+ if kerns then
+ local format = currentlookup.format
+ if format == "single" then
+ local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns) -- currentlookup.flags ?
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %s (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),format,dx,dy,w,h)
+ end
+ else -- needs checking .. maybe no kerns format for single
+ local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection)
+ if trace_kerns then
+ logprocess("%s: shifting single %s by %s %p",cref(dataset,sequence),gref(startchar),format,k)
+ end
end
+ return head, start, true
end
- return head, start, true
end
end
return head, start, false
end
function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex) -- todo: injections ?
- local mapping = currentlookup.mapping
- if mapping == nil then
- mapping = getmapping(dataset,sequence,currentlookup)
- end
- if mapping then
- local snext = getnext(start)
- if snext then
- local startchar = getchar(start)
- local kerns = mapping[startchar] -- always 1 step
- if kerns then
- local prev = start
- while snext do
- local nextchar = ischar(snext,currentfont)
- if not nextchar then
- break
- end
- if skiphash and skiphash[nextchar] then
- prev = snext
- snext = getnext(snext)
- else
- local krn = kerns[nextchar]
- if not krn then
+ if has_glyph_option(start,no_right_kern_code) then
+ local mapping = currentlookup.mapping
+ if mapping == nil then
+ mapping = getmapping(dataset,sequence,currentlookup)
+ end
+ if mapping then
+ local snext = getnext(start)
+ if snext then
+ local startchar = getchar(start)
+ local kerns = mapping[startchar] -- always 1 step
+ if kerns then
+ local prev = start
+ while snext do
+ local nextchar = ischar(snext,currentfont)
+ if not nextchar then
break
end
- local format = currentlookup.format
- if format == "pair" then
- local a = krn[1]
- local b = krn[2]
- if a == true then
- -- zero
- elseif a then
- local x, y, w, h = setposition(1,start,factor,rlmode,a,"injections") -- currentlookups flags?
- if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
- end
+ if skiphash and skiphash[nextchar] then
+ prev = snext
+ snext = getnext(snext)
+ else
+ local krn = kerns[nextchar]
+ if not krn then
+ break
end
- if b == true then
- -- zero
- start = snext -- cf spec
- elseif b then -- #b > 0
- local x, y, w, h = setposition(2,snext,factor,rlmode,b,"injections")
+ local format = currentlookup.format
+ if format == "pair" then
+ local a = krn[1]
+ local b = krn[2]
+ if a == true then
+ -- zero
+ elseif a then
+ local x, y, w, h = setposition(1,start,factor,rlmode,a,"injections") -- currentlookups flags?
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b == true then
+ -- zero
+ start = snext -- cf spec
+ elseif b then -- #b > 0
+ local x, y, w, h = setposition(2,snext,factor,rlmode,b,"injections")
+ if trace_kerns then
+ local startchar = getchar(start)
+ logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ start = snext -- cf spec
+ elseif forcepairadvance then
+ start = snext -- for testing, not cf spec
+ end
+ return head, start, true
+ elseif krn ~= 0 then
+ local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn)
if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
+ logprocess("%s: inserting %s %p between %s and %s",cref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar))
end
- start = snext -- cf spec
- elseif forcepairadvance then
- start = snext -- for testing, not cf spec
- end
- return head, start, true
- elseif krn ~= 0 then
- local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting %s %p between %s and %s",cref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar))
+ return head, start, true
+ else
+ break
end
- return head, start, true
- else
- break
end
end
end
@@ -3759,7 +3785,7 @@ do
local initialrl = 0
- if getid(head) == localpar_code and start_of_par(head) then
+ if getid(head) == par_code and start_of_par(head) then
initialrl = pardirstate(head)
elseif direction == righttoleft_code then
initialrl = -1
@@ -3913,7 +3939,7 @@ do
elseif id == dir_code then
topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
start = getnext(start)
- -- elseif id == localpar_code and start_of_par(start) then
+ -- elseif id == par_code and start_of_par(start) then
-- rlparmode, rlmode = pardirstate(start)
-- start = getnext(start)
else
@@ -3997,7 +4023,7 @@ do
elseif id == dir_code then
topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
start = getnext(start)
- -- elseif id == localpar_code and start_of_par(start) then
+ -- elseif id == par_code and start_of_par(start) then
-- rlparmode, rlmode = pardirstate(start)
-- start = getnext(start)
else
@@ -4108,7 +4134,7 @@ do
elseif id == dir_code then
topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
start = getnext(start)
- -- elseif id == localpar_code and start_of_par(start) then
+ -- elseif id == par_code and start_of_par(start) then
-- rlparmode, rlmode = pardirstate(start)
-- start = getnext(start)
else
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index 749c66fe7..19d4f3f7e 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -931,10 +931,14 @@
\unexpanded\def\normalss{\font_helpers_set_current_font_style{\s!ss}}
\unexpanded\def\normaltt{\font_helpers_set_current_font_style{\s!tt}}
+\pushoverloadmode
+
\let\rm\normalrm
\let\ss\normalss
\let\tt\normaltt
+\popoverloadmode
+
\protect \endinput
% LM math vs CM math (analysis by Taco):
diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua
index 643080788..c61873995 100644
--- a/tex/context/base/mkiv/font-sol.lua
+++ b/tex/context/base/mkiv/font-sol.lua
@@ -105,7 +105,7 @@ local disc_code = nodecodes.disc
local kern_code = nodecodes.kern
local hlist_code = nodecodes.hlist
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local whatsit_code = nodecodes.whatsit
@@ -437,7 +437,7 @@ function splitters.split(head) -- best also pass the direction
end
local direction, pop = getdirection(current)
r2l = not pop and direction == righttoleft_code
- elseif id == localpar_code and start_of_par(current) then
+ elseif id == par_code and start_of_par(current) then
if start then
flush() -- very unlikely as this starts a paragraph
end
diff --git a/tex/context/base/mkiv/font-sty.mklx b/tex/context/base/mkiv/font-sty.mklx
index f0fe65183..457217f8d 100644
--- a/tex/context/base/mkiv/font-sty.mklx
+++ b/tex/context/base/mkiv/font-sty.mklx
@@ -48,13 +48,10 @@
\setnewconstant \c_font_current_alternative_style_index \plusone
-\unexpanded\def\definealternativestyle
- {\dotripleempty\font_basics_define_alternative_style}
-
-\def\font_basics_define_alternative_style[#commands][#variantone][#varianttwo]%
+\permanent\tolerant\protected\def\definealternativestyle[#commands]#spacer[#variantone]#spacer[#varianttwo]%
{\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}}
-\let\definestyle\definealternativestyle % later redefined
+% \let\definestyle\definealternativestyle % later redefined
\newconstant\c_fonts_basics_alternative_style_method
@@ -66,7 +63,7 @@
\ifthirdargument
\setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}%
\else
- \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
+ \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
\fi
\else
\setuvalue{#command}{\triggergroupedcommand{#variantone}}%
@@ -83,7 +80,7 @@
\expandafter\firstoftwoarguments
\fi}
-\def\applyalternativestyle#name% public
+\permanent\def\applyalternativestyle#name% public .. expandable? frozen?
{\begincsname\??alternativestyle#name\endcsname}
\appendtoks
@@ -146,7 +143,7 @@
\let\m_current_convert_font \empty
\let\m_current_convert_font_dt\empty
-\unexpanded\def\doconvertfont#specification% takes second argument / this command is obsolete
+\permanent\protected\def\doconvertfont#specification% takes second argument / this command is obsolete
{\edef\m_current_convert_font{#specification}%
\ifempty\m_current_convert_font
%\expandafter\firstofoneargument
@@ -174,30 +171,33 @@
%D \chapter{This is \TEX}
%D \stoptyping
-\unexpanded\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage
-\unexpanded\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage
+\permanent\protected\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage
+\permanent\protected\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage
%D The new one:
\setfalse\fontattributeisset
-\unexpanded\def\dousestyleparameter#value%
+\let\currentstyleparameter \empty % these might become private (possible conflict with defines)
+\let\currentdetokenizedstyleparameter\empty % these might become private (possible conflict with defines)
+
+\permanent\protected\def\dousestyleparameter#value%
{\edef\currentstyleparameter{#value}%
\ifempty\currentstyleparameter\else
\expandafter\dousecurrentstyleparameter
\fi}
-\unexpanded\def\dousestylehashparameter#hash#parameter%
+\permanent\protected\def\dousestylehashparameter#hash#parameter%
{\ifcsname#hash#parameter\endcsname
\expandafter\dousestyleparameter\lastnamedcs
\fi}
-\unexpanded\def\dousecurrentstyleparameter % empty check outside here
- {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
+\permanent\protected\def\dousecurrentstyleparameter % empty check outside here
+ {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
\settrue\fontattributeisset % reset is done elsewhere
- \ifcsname\??alternativestyle\detokenizedstyleparameter\endcsname
+ \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname
\lastnamedcs
- \orelse\ifcsname\detokenizedstyleparameter\endcsname
+ \orelse\ifcsname\currentdetokenizedstyleparameter\endcsname
\lastnamedcs
\else
\currentstyleparameter
@@ -241,24 +241,24 @@
\fi
\to \everydefinestyle
-\unexpanded\def\font_styles_apply_start#name%
+\protected\def\font_styles_apply_start#name%
{\begingroup
\font_styles_use_defined{#name}}
-\unexpanded\def\font_styles_apply_stop
+\protected\def\font_styles_apply_stop
{\endgroup}
-\unexpanded\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup
+\protected\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup
{\bgroup
\def\g_style{\font_styles_use_defined{#name}}%
\afterassignment\g_style
\let\nexttoken}
-\unexpanded\def\font_styles_use_defined#name%
+\protected\def\font_styles_use_defined#name%
{\edef\currentstyle{#name}%
\usestylestyleandcolor\c!style\c!color}
-\unexpanded\def\font_styles_use_generic#specification%
+\protected\def\font_styles_use_generic#specification%
{\let\currentstyle\s!unknown % reasonable generic tag
\letstyleparameter\c!style\empty
\letstyleparameter\c!color\empty
@@ -269,7 +269,7 @@
\installcorenamespace{styleargument}
-\unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand
+\protected\def\style[#name]% as this is can be a switch we use groupedcommand % frozen?
{\csname\??styleargument
\ifcsname\??stylecheck#name\endcsname
2% defined as style
@@ -282,15 +282,9 @@
\fi
\endcsname{#name}}
-% \setvalue{\??styleargument1}#name%
-% {\groupedcommand{\begincsname#name\endcsname}{}}
-
\setvalue{\??styleargument1}#name%
{\expandafter\triggergroupedcommandcs\begincsname#name\endcsname}
-% \setvalue{\??styleargument2}#name%
-% {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}}
-
\setvalue{\??styleargument2}#name%
{\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}}
@@ -313,7 +307,7 @@
\installcorenamespace{styleenvironment}
-\unexpanded\def\startstyle[#name]%
+\protected\def\startstyle[#name]%
{\begingroup
\csname\??styleenvironment
\ifcsname\??stylecheck#name\endcsname
@@ -325,7 +319,7 @@
\fi
\endcsname{#name}}
-\unexpanded\def\stopstyle
+\protected\def\stopstyle
{\endgroup
\autoinsertnextspace} % will be configurable, maybe also in \definestartstop
@@ -355,11 +349,8 @@
\installcorenamespace{stylecollection}
-\unexpanded\def\definestylecollection
- {\dosingleargument\font_styles_define_style_collection}
-
-\def\font_styles_define_style_collection[#name]%
- {\iffirstargument
+\permanent\tolerant\protected\def\definestylecollection[#name]%
+ {\ifarguments\or
\setuvalue{#name}{\styleinstance[#name]}%
\def\font_styles_define_style_collection_a#style%
{\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}%
@@ -372,29 +363,19 @@
\let\font_styles_define_style_collection_a\relax
\let\font_styles_define_style_collection_b\relax
-\unexpanded\def\definestyleinstance
- {\doquadrupleargument\font_styles_define_style_instance}
-
-\def\font_styles_define_style_instance[#instance][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
- {\iffirstargument
+\permanent\tolerant\protected\def\definestyleinstance[#instance]#*[#2]#*[#3]#*[#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
+ {\ifparameter#instance\or
+ \ifarguments\or\or
+ \letvalueempty{\??stylecollection#instance::#2}%
+ \or
+ \setvalue{\??stylecollection#instance::#2}{#3}%
+ \or
+ \setvalue{\??stylecollection#instance:#2:#3}{#4}%
+ \fi
\ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi
- \fi
- \iffourthargument
- \setvalue{\??stylecollection#instance:#2:#3}{#4}%
- \orelse\ifthirdargument
- \setvalue{\??stylecollection#instance::#2}{#3}%
- \orelse\ifsecondargument
- \letvalueempty{\??stylecollection#instance::#2}%
- \fi}
-
-% \unexpanded\def\styleinstance[#instance]% will be made faster
-% {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup
-% \executeifdefined{\??stylecollection#instance:\fontstyle:\fontalternative}%
-% {\executeifdefined{\??stylecollection#instance:\fontstyle:\s!default}%
-% {\executeifdefined{\??stylecollection#instance::\fontalternative}
-% {\getvalue {\??stylecollection#instance::\s!default}}}}}
+ \fi}
-\unexpanded\def\styleinstance[#instance]% maybe \lastnamedcs here too
+\permanent\protected\def\styleinstance[#instance]% maybe \lastnamedcs here too
{\csname\??stylecollection#instance:%
\ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname
\fontstyle:\fontalternative
@@ -414,20 +395,20 @@
%D \mathematics {\utfchar{0x2229}\vsone{}}
%D \stoptyping
-\unexpanded\edef\vsone#character{#character\normalUchar"FE00 } % used
-\unexpanded\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing
+\permanent\protected\edef\vsone#character{#character\normalUchar"FE00 } % used
+\permanent\protected\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing
%D For historic reasons we keep the following around but they are no longer that
-%D relevant for \MKIV.
+%D relevant for \MKIV. But \unknown\ they will be dropped in \LMTX !
-\unexpanded\def\doattributes#1#2#3#4%
+\permanent\protected\def\doattributes#1#2#3#4%
{\begingroup % geen \bgroup, anders in mathmode lege \hbox
\dousestylehashparameter{#1}{#2}%
\dousecolorhashparameter{#1}{#3}%
#4%
\endgroup}
-\unexpanded\def\dostartattributes#1#2#3%
+\permanent\protected\def\dostartattributes#1#2#3%
{\begingroup % geen \bgroup, anders in mathmode lege \hbox
\dousestylehashparameter{#1}{#2}%
\dousecolorhashparameter{#1}{#3}}
@@ -438,16 +419,16 @@
\newconditional\c_font_styles_math
-\unexpanded\def\font_styles_math_reset
+\protected\def\font_styles_math_reset
{\setfalse\c_font_styles_math}
-\unexpanded\def\font_styles_math_start
+\protected\def\font_styles_math_start
{\ifconditional\c_font_styles_math
\startimath
\fi
\relax}
-\unexpanded\def\font_styles_math_stop
+\protected\def\font_styles_math_stop
{\relax
\ifconditional\c_font_styles_math
\stopimath
diff --git a/tex/context/base/mkiv/font-sty.mkvi b/tex/context/base/mkiv/font-sty.mkvi
index a24194355..519381a2e 100644
--- a/tex/context/base/mkiv/font-sty.mkvi
+++ b/tex/context/base/mkiv/font-sty.mkvi
@@ -181,6 +181,9 @@
\setfalse\fontattributeisset
+\let\currentstyleparameter \empty % these might become private
+\let\currentdetokenizedstyleparameter\empty % these might become private
+
\unexpanded\def\dousestyleparameter#value%
{\edef\currentstyleparameter{#value}%
\ifx\currentstyleparameter\empty\else
@@ -193,11 +196,11 @@
\fi}
\unexpanded\def\dousecurrentstyleparameter % empty check outside here
- {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
+ {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
\settrue\fontattributeisset % reset is done elsewhere
- \ifcsname\??alternativestyle\detokenizedstyleparameter\endcsname
+ \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname
\lastnamedcs
- \else\ifcsname\detokenizedstyleparameter\endcsname
+ \else\ifcsname\currentdetokenizedstyleparameter\endcsname
\lastnamedcs
\else
\currentstyleparameter
diff --git a/tex/context/base/mkiv/font-sym.mklx b/tex/context/base/mkiv/font-sym.mklx
index 33f8a62da..db80572e8 100644
--- a/tex/context/base/mkiv/font-sym.mklx
+++ b/tex/context/base/mkiv/font-sym.mklx
@@ -82,7 +82,9 @@
%D The next macro is used to map non latin fontnames on fonts. See \type
%D {font-uni} for an example of its use.
-\def\fontstylesuffix% why the \s!Regular ? see \getglyph
+% \frozen ...
+
+\permanent\def\fontstylesuffix% why the \s!Regular ? see \getglyph
{\ifx\fontalternative\s!tf \s!Regular \orelse
\ifx\fontalternative\s!bf \s!Bold \orelse
\ifx\fontalternative\s!sl \s!Slanted \orelse
@@ -92,7 +94,7 @@
\ifx\fontalternative\s!sc \s!Caps \else
\s!Regular \fi}
-\def\glyphfontfile#base% appends
+\permanent\def\glyphfontfile#base% appends
{#base%
\ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname
\v_font_string_a\v_font_string_c
@@ -108,7 +110,7 @@
%D The next macro can be used to make decisions based on the shape:
-\def\doifelseitalic#yes#nop%
+\permanent\def\doifelseitalic#yes#nop%
{\ifx\fontalternative\s!sl#yes\orelse
\ifx\fontalternative\s!it#yes\orelse
\ifx\fontalternative\s!bs#yes\orelse
@@ -129,7 +131,7 @@
\let\thedefinedfont\relax
-\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+\permanent\protected\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
{\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
\ifcsname\??symbolfont\askedsymbolfont\endcsname
\lastnamedcs
@@ -137,7 +139,7 @@
\font_basics_define_symbolic_font
\fi}
-\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
+\permanent\protected\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
{\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
\ifcsname\??symbolfont\askedsymbolfont\endcsname
\lastnamedcs
@@ -145,7 +147,7 @@
\font_basics_define_symbolic_font
\fi}
-\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
+\permanent\protected\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
{\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
\ifcsname\??symbolfont\askedsymbolfont\endcsname
\lastnamedcs
@@ -153,7 +155,7 @@
\font_basics_define_symbolic_font
\fi}
-\def\setdirectsymbolicfont#fontname%
+\permanent\protected\def\setdirectsymbolicfont#fontname%
{\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
\ifcsname\??symbolfont\askedsymbolfont\endcsname
\lastnamedcs
@@ -166,16 +168,16 @@
\currentsymbolfont
\expandafter\glet\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
-\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}}
-\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}}
-\unexpanded\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
-\unexpanded\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
-\unexpanded\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}}
-\unexpanded\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}}
+\permanent\protected\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\permanent\protected\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}}
+\permanent\protected\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+\permanent\protected\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}}
+\permanent\protected\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}}
+\permanent\protected\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}}
% this one is wrong:
-\unexpanded\def\getscaledglyph#scale#name#content%
+\permanent\protected\def\getscaledglyph#scale#name#content%
{{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}}
\let\getglyph \getglyphstyled % old
@@ -183,8 +185,7 @@
\let\symbolicsizedfont\setscaledstyledsymbolicfont % old
\let\symbolicfont \setstyledsymbolicfont % old
-\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
-\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
+\permanent\protected\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
%D The last implementation of \type {\getglyph} permits definitions like:
%D
@@ -215,7 +216,7 @@
%D Every now and then we want to define a font directly, for instance when we
%D typeset title pages. The next macro saves some typing:
-\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk
+\permanent\protected\def\setfont% geen \font_helpers_set_font mogelijk
{\afterassignment\font_basics_set_font\font\nextfont=}
\def\font_basics_set_font
@@ -231,7 +232,7 @@
%D \macros{doiffontcharelse}
-\unexpanded\def\doifelsefontchar#specification#unicode% this could be a direct lua call
+\permanent\protected\def\doifelsefontchar#specification#unicode% this could be a direct lua call
{\begingroup
\font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
\iffontchar\font#unicode\relax
@@ -240,6 +241,6 @@
\endgroup\expandafter\secondoftwoarguments
\fi}
-\let\doiffontcharelse\doifelsefontchar
+\aliased\let\doiffontcharelse\doifelsefontchar
\protect \endinput
diff --git a/tex/context/base/mkiv/font-tra.mkiv b/tex/context/base/mkiv/font-tra.mkiv
index 7d02cd140..99c7ab3c8 100644
--- a/tex/context/base/mkiv/font-tra.mkiv
+++ b/tex/context/base/mkiv/font-tra.mkiv
@@ -357,7 +357,7 @@
% new
-\unexpanded\def\savefont[#1]% not yet in i-*.xml
+\unexpanded\def\savefontdata[#1]% not yet in i-*.xml
{\begingroup
\getdummyparameters[#1]%
\clf_savefont {
diff --git a/tex/context/base/mkiv/grph-epd.lua b/tex/context/base/mkiv/grph-epd.lua
index f8fa62953..0993270f1 100644
--- a/tex/context/base/mkiv/grph-epd.lua
+++ b/tex/context/base/mkiv/grph-epd.lua
@@ -40,7 +40,7 @@ local function mergegoodies(optionlist)
end
function figures.mergegoodies(optionlist)
- -- todo: we can use runtoks instead
+ -- todo: we can use runlocal instead
context.stepwise(function()
-- we use stepwise because we might need to define symbols
-- for stamps that have no default appearance
diff --git a/tex/context/base/mkiv/grph-fig.mkiv b/tex/context/base/mkiv/grph-fig.mkiv
index 3bf3248a6..c196d1420 100644
--- a/tex/context/base/mkiv/grph-fig.mkiv
+++ b/tex/context/base/mkiv/grph-fig.mkiv
@@ -256,6 +256,9 @@
\tpack{\vskip12\points\box2\vskip6\points}}%
\endgroup}
+\definesystemconstant {vwa}
+\definesystemconstant {vwb}
+
\unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]%
{\advance\c_grph_steps_reference\plusone
\position(#1,#2)
diff --git a/tex/context/base/mkiv/grph-pat.mkxl b/tex/context/base/mkiv/grph-pat.mkxl
new file mode 100644
index 000000000..df30258bc
--- /dev/null
+++ b/tex/context/base/mkiv/grph-pat.mkxl
@@ -0,0 +1,119 @@
+%D \module
+%D [ file=grph-par,
+%D version=2016.07.08,
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Patterns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This works ok in Okular and MuPDF but somehow xforms don't work in Acrobat
+%D (full nor reader). Also the basic offset is kind of unspecified. So \unknown\
+%D we're dealing with a fragile feature. So, don't rely on where the first (ulr)
+%D tile occurs.
+%D
+%D The two commands introduced here are not documented (yet).
+
+\writestatus{loading}{ConTeXt Graphic Macros / Patterns}
+
+\unprotect
+
+\registerctxluafile{grph-pat}{}
+
+\permanent\tolerant\protected\def\registerpattern[#1]#*[#2]%
+ {\begingroup
+ \letdummyparameter\c!name \s!dummy
+ \letdummyparameter\c!width \v!auto
+ \letdummyparameter\c!height \v!auto
+ \letdummyparameter\c!hoffset\zeropoint
+ \letdummyparameter\c!voffset\zeropoint
+ \unless\iftok{#2}\emptytoks
+ \setdummyparameter\c!name{#1}%
+ \getdummyparameters[#2]%
+ \orelse\ifhastok={#1}%
+ \getdummyparameters[#1]%
+ \else
+ \setdummyparameter\c!name{#1}%
+ \fi
+ \dowithnextboxcs\syst_boxes_registerpattern_indeed\hbox}
+
+\immutable\edef\v!auto_m{-\v!auto}
+
+\def\syst_boxes_registerpattern_indeed
+ {%\finalizeobjectbox\nextbox
+ \edef\p_width {\dummyparameter\c!width}%
+ \edef\p_height {\dummyparameter\c!height}%
+ \edef\p_hoffset{\dummyparameter\c!hoffset}%
+ \edef\p_voffset{\dummyparameter\c!voffset}%
+ \scratchwidth \dimexpr\ifx\p_width \v!auto\wd \nextbox \else\p_width \fi\relax
+ \scratchheight \dimexpr\ifx\p_height \v!auto\htdp\nextbox \else\p_height \fi\relax
+ \scratchhoffset\dimexpr\ifx\p_hoffset\v!auto\scratchwidth /2\else\ifx\p_hoffset\v!auto_m-\scratchwidth /2\else\p_hoffset\fi\fi\relax
+ \scratchvoffset\dimexpr\ifx\p_voffset\v!auto\scratchheight/2\else\ifx\p_voffset\v!auto_m-\scratchheight/2\else\p_voffset\fi\fi\relax
+ \clf_registerpattern
+ name {\dummyparameter\c!name}
+ number \nextbox
+ width \scratchwidth
+ height \scratchheight
+ hoffset \scratchhoffset
+ voffset \scratchvoffset
+ \relax
+ \endgroup}
+
+\permanent\tolerant\protected\def\applypattern[#1]#*[#2]%
+ {\hbox\bgroup
+ \letdummyparameter\c!name \s!dummy
+ \letdummyparameter\c!width \zeropoint
+ \letdummyparameter\c!height\zeropoint
+ \unless\iftok{#2}\emptytoks
+ \setdummyparameter\c!name{#1}%
+ \getdummyparameters[#2]%
+ \orelse\ifhastok={#1}%
+ \getdummyparameters[#1]%
+ \else
+ \setdummyparameter\c!name{#1}%
+ \fi
+ \clf_applypattern
+ name {\dummyparameter\c!name}
+ number \nextbox
+ width \dimexpr\dummyparameter\c!width\relax
+ height \dimexpr\dummyparameter\c!height\relax
+ \relax
+ \box\nextbox
+ \egroup}
+
+\protect
+
+\continueifinputfile{grph-pat.mkxl}
+
+\nopdfcompression
+
+\starttext
+
+ \registerpattern[demo]{It \darkred Works!}
+
+ \framed[offset=overlay]{\applypattern[demo][width=7cm,height=4cm]}
+
+ \blank
+
+ \registerpattern[name=more,hoffset=0bp,voffset=0pt]{\externalfigure[cow.pdf][width=1cm]}
+
+ \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]}
+
+ \blank
+
+ \registerpattern[name=more,hoffset=auto,voffset=auto]{\externalfigure[cow.pdf][width=1cm]}
+
+ \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]}
+
+ \blank
+
+ \registerpattern[name=more,hoffset=-auto,voffset=-auto]{\externalfigure[cow.pdf][width=1cm]}
+
+ \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]}
+
+\stoptext
+
diff --git a/tex/context/base/mkiv/grph-trf.mkiv b/tex/context/base/mkiv/grph-trf.mkiv
index d6a6acd78..d1be7e1d7 100644
--- a/tex/context/base/mkiv/grph-trf.mkiv
+++ b/tex/context/base/mkiv/grph-trf.mkiv
@@ -234,11 +234,20 @@
{\ifdim\p_sx\onepoint=\onepoint\else\edef\p_width {\the\dimexpr\p_sx\d_grph_scale_wd}\fi
\ifdim\p_sy\onepoint=\onepoint\else\edef\p_height{\the\dimexpr\p_sy\d_grph_scale_ht}\fi}
-\def\grph_scale_rounded#1%
- {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
- \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax}
+\ifcase\contextlmtxmode
-\def\grph_scale_rounded_indeed#1.#2\relax{#1}
+ \def\grph_scale_rounded#1%
+ {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
+ \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax}
+
+ \def\grph_scale_rounded_indeed#1.#2\relax{#1}
+
+\else
+
+ \def\grph_scale_rounded#1%
+ {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax}
+
+\fi
\def\grph_scale_calculations_nop
{\settrue\c_grph_scale_done
diff --git a/tex/context/base/mkiv/hand-ini.mkxl b/tex/context/base/mkiv/hand-ini.mkxl
index 9c291fed8..3fd82f239 100644
--- a/tex/context/base/mkiv/hand-ini.mkxl
+++ b/tex/context/base/mkiv/hand-ini.mkxl
@@ -37,26 +37,27 @@
\unprotect
-%D New stuff.
+%D Probbaly not yet used by many.
-\unexpanded\def\setupfontexpansion {\dodoubleargument\font_expansion_setup }
-\unexpanded\def\setupfontprotrusion{\dodoubleargument\font_protrusion_setup}
-
-\def\font_expansion_setup [#1][#2]{\clf_setupfontexpansion {#1}{#2}}
-\def\font_protrusion_setup[#1][#2]{\clf_setupfontprotrusion{#1}{#2}}
+\permanent\tolerant\protected\def\setupfontexpansion [#1]#*[#2]{\clf_setupfontexpansion {#1}{#2}}
+\permanent\tolerant\protected\def\setupfontprotrusion[#1]#*[#2]{\clf_setupfontprotrusion{#1}{#2}}
% \setupfontprotrusion[quality-upright][vector=quality]
% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5]
-\let\adjustspacing\relax \newcount\adjustspacing % a little bit protection
-\let\protrudechars\relax \newcount\protrudechars % a little bit protection
+\pushoverloadmode
+
+ \let\adjustspacing\relax \newcount\adjustspacing % a little bit protection
+ \let\protrudechars\relax \newcount\protrudechars % a little bit protection
-% at some point we can introduce extreme expansion, i.e. \normaladjustspacing\plustwo
+\popoverloadmode
+
+%D At some point we can introduce extreme expansion, i.e. \type {\normaladjustspacing\plustwo}.
% 0 = disabled
-% 1 = notused (thesis)
+% 1 = notused (thesis)
% 2 = glyph + kern
-% 3 = glyph only
+% 3 = glyph only (default)
\def\font_expansion_enable {\normaladjustspacing\plusthree}
\def\font_expansion_enable_k{\normaladjustspacing\plustwo}
@@ -74,9 +75,9 @@
%
% \let\fonthandling\empty
%
-% \unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
-% \unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling}
-% \unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
+% \protected\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
+% \protected\def\definefonthandling {\dotripleempty\dodefinefonthandling}
+% \protected\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
% \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror}
% \def\dosetupfonthandling [#1][#2]{\fonthandlingerror}
% \def\usehandling [#1]{\fonthandlingerror}
@@ -102,10 +103,11 @@
% [\c!stretch=50,
% \c!shrink=20]
-\unexpanded\def\setexpansion
- {\dosingleempty\font_expansion_set}
+\permanent\tolerant\protected\def\setexpansion[#1]{\begincsname\??expansion:#1\endcsname}
+
+%D New in \LMTX: can be used grouped.
-\unexpanded\def\font_expansion_set[#1]%
- {\begincsname\??expansion:#1\endcsname}
+\permanent\protected\def\noexpansion {\bitwiseflip\glyphoptions\noexpansioncode}
+\permanent\protected\def\noprotrusion{\bitwiseflip\glyphoptions\noprotrusioncode}
\protect \endinput
diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv
index 35a634644..f2364a128 100644
--- a/tex/context/base/mkiv/lang-def.mkiv
+++ b/tex/context/base/mkiv/lang-def.mkiv
@@ -489,6 +489,22 @@
% Artificial Languages: Esperanto
+\installlanguage
+ [\s!esperanto]
+ [%\c!spacing=\v!packed,
+ %\c!leftsentence=\emdash,
+ %\c!rightsentence=\emdash,
+ %\c!leftsubsentence=\emdash,
+ %\c!rightsubsentence=\emdash,
+ %\c!leftquote=\lowerleftdoubleninequote,
+ %\c!rightquote=\upperrightdoublesixquote,
+ %\c!leftquotation=\lowerleftdoubleninequote,
+ %\c!rightquotation=\upperrightdoublesixquote,
+ %\c!date={\v!year,~m.,\space,\v!month,\space,\v!day,~d.},
+ \s!patterns=eo,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2]
+
% Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian
\installlanguage
diff --git a/tex/context/base/mkiv/lang-dis.lmt b/tex/context/base/mkiv/lang-dis.lmt
new file mode 100644
index 000000000..263225691
--- /dev/null
+++ b/tex/context/base/mkiv/lang-dis.lmt
@@ -0,0 +1,222 @@
+if not modules then modules = { } end modules ['lang-dis'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+
+local tex = tex
+local nodes = nodes
+
+local tasks = nodes.tasks
+local nuts = nodes.nuts
+
+local enableaction = tasks.enableaction
+local setaction = tasks.setaction
+
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getattr = nuts.getattr
+local getsubtype = nuts.getsubtype
+local setsubtype = nuts.setsubtype
+local getchar = nuts.getchar
+local setchar = nuts.setchar
+local getdisc = nuts.getdisc
+local setdisc = nuts.setdisc
+local getlanguage = nuts.getlanguage
+local getboth = nuts.getboth
+local setlist = nuts.setlist
+local setlink = nuts.setlink
+local isglyph = nuts.isglyph
+
+local copy_node = nuts.copy
+local remove_node = nuts.remove
+local flush_list = nuts.flush_list
+local flush_node = nuts.flush_node
+
+local nextdisc = nuts.traversers.disc
+
+local new_disc = nuts.pool.disc
+
+local nodecodes = nodes.nodecodes
+local disccodes = nodes.disccodes
+
+local disc_code = nodecodes.disc
+local glyph_code = nodecodes.glyph
+
+local explicitdisc_code = disccodes.explicit
+
+local a_visualize = attributes.private("visualizediscretionary")
+local setattribute = tex.setattribute
+
+local getlanguagedata = languages.getdata
+local prehyphenchar = language.prehyphenchar
+local posthyphenchar = language.posthyphenchar
+
+local check_regular = true
+
+local setlistcolor = nodes.tracers.colors.setlist
+
+function languages.visualizediscretionaries(head)
+ for d in nextdisc, head do
+ if getattr(d,a_visualize) then
+ local pre, post, replace = getdisc(d)
+ if pre then
+ setlistcolor(pre,"darkred")
+ end
+ if post then
+ setlistcolor(post,"darkgreen")
+ end
+ if replace then
+ setlistcolor(replace,"darkblue")
+ end
+ end
+ end
+ return head
+end
+
+local enabled = false
+
+function languages.showdiscretionaries(v)
+ if v == false then
+ setattribute(a_visualize,unsetvalue)
+ else -- also nil
+ if not enabled then
+ enableaction("processors","languages.visualizediscretionaries")
+ enabled = true
+ end
+ setattribute(a_visualize,1)
+ end
+end
+
+interfaces.implement {
+ name = "showdiscretionaries",
+ actions = languages.showdiscretionaries
+}
+
+do
+
+ local toutf = nodes.listtoutf
+ local utfchar = utf.char
+ local f_disc = string.formatters["{%s}{%s}{%s}"]
+ local replace = lpeg.replacer( {
+ [utfchar(0x200C)] = "|",
+ [utfchar(0x200D)] = "|",
+ }, nil, true)
+
+ local function convert(list)
+ return list and replace(toutf(list)) or ""
+ end
+
+ function languages.serializediscretionary(d) -- will move to tracer
+ local pre, post, replace = getdisc(d)
+ return f_disc(convert(pre),convert(post),convert(replace))
+ end
+
+end
+
+-- --
+
+local wiped = 0
+
+local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes
+
+-- if flatten_discretionaries then
+
+ function languages.flatten(head)
+ local h, n = flatten_discretionaries(head)
+ wiped = wiped + n
+ return h, n > 0
+ end
+
+-- else
+--
+-- local function wipe(head,delayed)
+-- local p, n = getboth(delayed)
+-- local _, _, h, _, _, t = getdisc(delayed,true)
+-- if p or n then
+-- if h then
+-- setlink(p,h)
+-- setlink(t,n)
+-- setfield(delayed,"replace")
+-- else
+-- setlink(p,n)
+-- end
+-- end
+-- if head == delayed then
+-- head = h
+-- end
+-- wiped = wiped + 1
+-- flush_node(delayed)
+-- return head
+-- end
+--
+-- function languages.flatten(head)
+-- local delayed = nil
+-- for d in nextdisc, head do
+-- if delayed then
+-- head = wipe(head,delayed)
+-- end
+-- delayed = d
+-- end
+-- if delayed then
+-- return wipe(head,delayed), true
+-- else
+-- return head, false
+-- end
+-- end
+--
+-- end
+
+function languages.nofflattened()
+ return wiped -- handy for testing
+end
+
+-- experiment: for now not in not in export mode!
+
+local flatten = languages.flatten
+
+nodes.handlers.flattenline = flatten
+
+function nodes.handlers.flatten(head,where)
+ if head and (where == "box" or where == "adjusted_hbox") then
+ return flatten(head)
+ end
+ return head
+end
+
+directives.register("hyphenator.flatten",function(v)
+ -- use with care
+ setaction("processors","nodes.handlers.flatten",v)
+ setaction("contributers","nodes.handlers.flattenline",v)
+end)
+
+-- moved here:
+
+function languages.explicithyphen(template)
+ local pre, post
+ local disc = new_disc()
+ if template then
+ local langdata = getlanguagedata(getlanguage(template))
+ local instance = langdata and langdata.instance
+ if instance then
+ local prechr = prehyphenchar(instance)
+ local postchr = posthyphenchar(instance)
+ if prechr >= 0 then
+ pre = copy_node(template)
+ setchar(pre,prechr)
+ end
+ if postchr >= 0 then
+ post = copy_node(template)
+ setchar(post,postchr)
+ end
+ end
+ end
+ setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty)
+ return disc
+end
diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua
index 90e84f65d..3e4678801 100644
--- a/tex/context/base/mkiv/lang-dis.lua
+++ b/tex/context/base/mkiv/lang-dis.lua
@@ -28,7 +28,7 @@ local getchar = nuts.getchar
local setchar = nuts.setchar
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
-local getlang = nuts.setlang
+local getlanguage = nuts.getlanguage
local getboth = nuts.getboth
local setlist = nuts.setlist
local setlink = nuts.setlink
diff --git a/tex/context/base/mkiv/lang-exp.lua b/tex/context/base/mkiv/lang-exp.lua
index 254961ee6..c2eb46990 100644
--- a/tex/context/base/mkiv/lang-exp.lua
+++ b/tex/context/base/mkiv/lang-exp.lua
@@ -116,7 +116,7 @@ if LUATEXVERSION < 1.005 then -- not loaded any more
end
end
if template then
- local language = template and getlang(template)
+ local language = template and getlanguage(template)
local data = getlanguagedata(language)
local prechar = data.prehyphenchar
local postchar = data.posthyphenchar
diff --git a/tex/context/base/mkiv/lang-hyp.lmt b/tex/context/base/mkiv/lang-hyp.lmt
new file mode 100644
index 000000000..c2862f536
--- /dev/null
+++ b/tex/context/base/mkiv/lang-hyp.lmt
@@ -0,0 +1,1806 @@
+if not modules then modules = { } end modules ['lang-hyp'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- In an automated workflow hypenation of long titles can be somewhat problematic
+-- especially when demands conflict. For that reason I played a bit with a Lua based
+-- variant of the traditional hyphenation machinery. This mechanism has been extended
+-- several times in projects, of which a good description can be found in TUGboat,
+-- Volume 27 (2006), No. 2 — Proceedings of EuroTEX2006: Automatic non-standard
+-- hyphenation in OpenOffice.org by László Németh.
+--
+-- Being the result of two days experimenting the following implementation is probably
+-- not completely okay yet. If there is demand I might add some more features and plugs.
+-- The performance is quite okay but can probably improved a bit, although this is not
+-- the most critital code. For instance, on a metafun manual run the overhead is about
+-- 0.3 seconds on 19 seconds which is not that bad.
+--
+-- In the procecess of wrapping up (for the ctx conference proceedings) I cleaned up
+-- and extended the code a bit. It can be used in production.
+--
+-- . a l g o r i t h m .
+-- 4l1g4
+-- l g o3
+-- 1g o
+-- 2i t h
+-- 4h1m
+-- ---------------------
+-- 4 1 4 3 2 0 4 1
+-- a l-g o-r i t h-m
+
+-- . a s s z o n n y a l .
+-- s1s z/sz=sz,1,3
+-- n1n y/ny=ny,1,3
+-- -----------------------
+-- 0 1 0 0 0 1 0 0 0/sz=sz,2,3,ny=ny,6,3
+-- a s-s z o n-n y a l/sz=sz,2,3,ny=ny,6,3
+--
+-- ab1cd/ef=gh,2,2 : acd - efd (pattern/replacement,start,length
+--
+-- todo : support hjcodes (<32 == length) like luatex does now (no need/demand so far)
+-- maybe : support hyphenation over range (can alsready be done using attributes/language)
+-- maybe : reset dictionary.hyphenated when a pattern is added and/or forced reset option
+-- todo : check subtypes (because they have subtle meanings in the line breaking)
+--
+-- word start (in tex engine):
+--
+-- boundary : yes when wordboundary
+-- hlist : when hyphenationbounds 1 or 3
+-- vlist : when hyphenationbounds 1 or 3
+-- rule : when hyphenationbounds 1 or 3
+-- dir : when hyphenationbounds 1 or 3
+-- whatsit : when hyphenationbounds 1 or 3
+-- glue : yes
+-- math : skipped
+-- glyph : exhyphenchar (one only) : yes (so no -- ---)
+-- otherwise : yes
+--
+-- word end (in tex engine):
+--
+-- boundary : yes
+-- glyph : yes when different language
+-- glue : yes
+-- penalty : yes
+-- kern : yes when not italic (for some historic reason)
+-- hlist : when hyphenationbounds 2 or 3
+-- vlist : when hyphenationbounds 2 or 3
+-- rule : when hyphenationbounds 2 or 3
+-- dir : when hyphenationbounds 2 or 3
+-- whatsit : when hyphenationbounds 2 or 3
+-- ins : when hyphenationbounds 2 or 3
+-- adjust : when hyphenationbounds 2 or 3
+
+local type, rawget, rawset, tonumber, next = type, rawget, rawset, tonumber, next
+
+local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs
+local lpegmatch = lpeg.match
+
+local context = context
+
+local concat = table.concat
+local insert = table.insert
+local remove = table.remove
+local formatters = string.formatters
+local utfchar = utf.char
+local utfbyte = utf.byte
+
+if not characters then
+ require("char-ini")
+end
+
+local setmetatableindex = table.setmetatableindex
+
+-- \enabletrackers[hyphenator.steps=silent] will not write to the terminal
+
+local trace_steps = false trackers.register("hyphenator.steps", function(v) trace_steps = v end)
+local trace_visualize = false trackers.register("hyphenator.visualize",function(v) trace_visualize = v end)
+
+local report = logs.reporter("hyphenator")
+
+local implement = interfaces and interfaces.implement or function() end
+
+languages = languages or { }
+local hyphenators = languages.hyphenators or { }
+languages.hyphenators = hyphenators
+local traditional = hyphenators.traditional or { }
+hyphenators.traditional = traditional
+
+local dictionaries = setmetatableindex(function(t,k)
+ local v = {
+ patterns = { },
+ hyphenated = { },
+ specials = { },
+ exceptions = { },
+ loaded = false,
+ }
+ t[k] = v
+ return v
+end)
+
+hyphenators.dictionaries = dictionaries
+
+local character = lpeg.patterns.utf8character
+local digit = R("09")
+local weight = digit/tonumber + Cc(0)
+local fence = P(".")
+local hyphen = P("-")
+local space = P(" ")
+local char = character - space
+local validcharacter = (character - S("./"))
+local keycharacter = character - S("/")
+----- basepart = Ct( (Cc(0) * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc(0))^-1)
+local specpart = (P("/") * Cf ( Ct("") *
+ Cg ( Cc("before") * C((1-P("="))^1) * P("=") ) *
+ Cg ( Cc("after") * C((1-P(","))^1) ) *
+ ( P(",") *
+ Cg ( Cc("start") * ((1-P(","))^1/tonumber) * P(",") ) *
+ Cg ( Cc("length") * ((1-P(-1) )^1/tonumber) )
+ )^-1
+ , rawset))^-1
+
+local make_hashkey_p = Cs((digit/"" + keycharacter)^1)
+----- make_pattern_p = basepart * specpart
+local make_hashkey_e = Cs((hyphen/"" + keycharacter)^1)
+local make_pattern_e = Ct(P(char) * (hyphen * Cc(true) * P(char) + P(char) * Cc(false))^1) -- catch . and char after -
+
+-- local make_hashkey_c = Cs((digit + keycharacter/"")^1)
+-- local make_pattern_c = Ct((P(1)/tonumber)^1)
+
+-- local cache = setmetatableindex(function(t,k)
+-- local n = lpegmatch(make_hashkey_c,k)
+-- local v = lpegmatch(make_pattern_c,n)
+-- t[k] = v
+-- return v
+-- end)
+--
+-- local weight_n = digit + Cc("0")
+-- local basepart_n = Cs( (Cc("0") * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc("0"))^-1) / cache
+-- local make_pattern_n = basepart_n * specpart
+
+local make_pattern_c = Ct((P(1)/tonumber)^1)
+
+-- us + nl: 17664 entries -> 827 unique (saves some 3M)
+
+local cache = setmetatableindex(function(t,k)
+ local v = lpegmatch(make_pattern_c,k)
+ t[k] = v
+ return v
+end)
+
+local weight_n = digit + Cc("0")
+local fence_n = fence / "0"
+local char_n = validcharacter / ""
+local basepart_n = Cs(fence_n^-1 * (weight_n * char_n)^1 * weight_n * fence_n^-1) / cache
+local make_pattern_n = basepart_n * specpart
+
+local function register_pattern(patterns,specials,str,specification)
+ local k = lpegmatch(make_hashkey_p,str)
+ -- local v1, v2 = lpegmatch(make_pattern_p,str)
+ local v1, v2 = lpegmatch(make_pattern_n,str)
+ patterns[k] = v1 -- is this key still ok for complex patterns
+ if specification then
+ specials[k] = specification
+ elseif v2 then
+ specials[k] = v2
+ end
+end
+
+local function unregister_pattern(patterns,specials,str)
+ local k = lpegmatch(make_hashkey_p,str)
+ patterns[k] = nil
+ specials[k] = nil
+end
+
+local p_lower = lpeg.patterns.utf8lower
+
+local function register_exception(exceptions,str,specification)
+ local l = lpegmatch(p_lower,str)
+ local k = lpegmatch(make_hashkey_e,l)
+ local v = lpegmatch(make_pattern_e,l)
+ exceptions[k] = v
+end
+
+local p_pattern = ((Carg(1) * Carg(2) * C(char^1)) / register_pattern + 1)^1
+local p_exception = ((Carg(1) * C(char^1)) / register_exception + 1)^1
+local p_split = Ct(C(character)^1)
+
+function traditional.loadpatterns(language,filename)
+ local dictionary = dictionaries[language]
+ if not dictionary.loaded then
+ if not filename or filename == "" then
+ filename = "lang-" .. language
+ end
+ filename = file.addsuffix(filename,"lua")
+ local fullname = resolvers.findfile(filename)
+ if fullname and fullname ~= "" then
+ local specification = dofile(fullname)
+ if specification then
+ local patterns = specification.patterns
+ if patterns then
+ local data = patterns.data
+ if data and data ~= "" then
+ lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials)
+ end
+ end
+ local exceptions = specification.exceptions
+ if exceptions then
+ local data = exceptions.data
+ if data and data ~= "" then
+ lpegmatch(p_exception,data,1,dictionary.exceptions)
+ end
+ end
+ end
+ end
+ dictionary.loaded = true
+ end
+ return dictionary
+end
+
+local lcchars = characters.lcchars
+local uccodes = characters.uccodes
+local categories = characters.categories
+local nofwords = 0
+local nofhashed = 0
+
+local steps = nil
+local f_show = formatters["%w%s"]
+
+local function show_log()
+ if trace_steps == true then
+ report()
+ local w = #steps[1][1]
+ for i=1,#steps do
+ local s = steps[i]
+ report("%s%w%S %S",s[1],w - #s[1] + 3,s[2],s[3] or "")
+ end
+ report()
+ end
+end
+
+local function show_1(wsplit)
+ local u = concat(wsplit," ")
+ steps = { { f_show(0,u), f_show(0,u) } }
+end
+
+local function show_2(c,m,wsplit,done,i,spec)
+ local s = lpegmatch(p_split,c)
+ local t = { }
+ local n = #m
+ local w = #wsplit
+ for j=1,n do
+ t[#t+1] = m[j]
+ t[#t+1] = s[j]
+ end
+ local m = 2*i-2
+ local l = #t
+ local s = spec and table.sequenced(spec) or ""
+ if m == 0 then
+ steps[#steps+1] = { f_show(m, concat(t,"",2)), f_show(1,concat(done," ",2,#done),s) }
+ elseif i+1 == w then
+ steps[#steps+1] = { f_show(m-1,concat(t,"",1,#t-1)), f_show(1,concat(done," ",2,#done),s) }
+ else
+ steps[#steps+1] = { f_show(m-1,concat(t)), f_show(1,concat(done," ",2,#done),s) }
+ end
+end
+
+local function show_3(wsplit,done)
+ local t = { }
+ local h = { }
+ local n = #wsplit
+ for i=1,n do
+ local w = wsplit[i]
+ if i > 1 then
+ local d = done[i]
+ t[#t+1] = i > 2 and d % 2 == 1 and "-" or " "
+ h[#h+1] = d
+ end
+ t[#t+1] = w
+ h[#h+1] = w
+ end
+ steps[#steps+1] = { f_show(0,concat(h)), f_show(0,concat(t)) }
+ show_log()
+end
+
+local function show_4(wsplit,done)
+ steps = { { concat(wsplit," ") } }
+ show_log()
+end
+
+function traditional.lasttrace()
+ return steps
+end
+
+-- We could reuse the w table but as we cache the resolved words there is not much gain in
+-- that complication.
+--
+-- Beware: word can be a table and when n is passed to we can assume reuse so we need to
+-- honor that n then.
+--
+-- todo: a fast variant for tex ... less lookups (we could check is dictionary has changed)
+-- ... although due to caching the already done words, we don't do much here
+
+local function hyphenate(dictionary,word,n) -- odd is okay
+ nofwords = nofwords + 1
+ local hyphenated = dictionary.hyphenated
+ local isstring = type(word) == "string"
+ if isstring then
+ local done = hyphenated[word]
+ if done ~= nil then
+ return done
+ end
+ elseif n then
+ local done = hyphenated[concat(word,"",1,n)]
+ if done ~= nil then
+ return done
+ end
+ else
+ local done = hyphenated[concat(word)]
+ if done ~= nil then
+ return done
+ end
+ end
+ local key
+ if isstring then
+ key = word
+ word = lpegmatch(p_split,word)
+ if not n then
+ n = #word
+ end
+ else
+ if not n then
+ n = #word
+ end
+ key = concat(word,"",1,n)
+ end
+ local l = 1
+ local w = { "." }
+ -- local d = dictionary.codehash
+ for i=1,n do
+ local c = word[i]
+ -- l = l + (d[c] or 1)
+ l = l + 1
+ w[l] = lcchars[c] or c
+ end
+ l = l + 1
+ w[l] = "."
+ local c = concat(w,"",2,l-1)
+ --
+ local done = hyphenated[c]
+ if done ~= nil then
+ hyphenated[key] = done
+ nofhashed = nofhashed + 1
+ return done
+ end
+ --
+ local exceptions = dictionary.exceptions
+ local exception = exceptions[c]
+ if exception then
+ if trace_steps then
+ show_4(w,exception)
+ end
+ hyphenated[key] = exception
+ nofhashed = nofhashed + 1
+ return exception
+ end
+ --
+ if trace_steps then
+ show_1(w)
+ end
+ --
+ local specials = dictionary.specials
+ local patterns = dictionary.patterns
+ --
+ local spec
+ for i=1,l do
+ for j=i,l do
+ local c = concat(w,"",i,j)
+ local m = patterns[c]
+ if m then
+ local s = specials[c]
+ if not done then
+ done = { }
+ spec = nil
+ -- the string that we resolve has explicit fences (.) so done starts at
+ -- the first fence and runs upto the last one so we need one slot less
+ for i=1,l do
+ done[i] = 0
+ end
+ end
+ -- we run over the pattern that always has a (zero) value for each character
+ -- plus one more as we look at both sides
+ for k=1,#m do
+ local new = m[k]
+ if not new then
+ break
+ elseif new == true then
+ report("fatal error")
+ break
+ elseif new > 0 then
+ local pos = i + k - 1
+ local old = done[pos]
+ if not old then
+ -- break ?
+ elseif new > old then
+ done[pos] = new
+ if s then
+ local b = i + (s.start or 1) - 1
+ if b > 0 then
+ local e = b + (s.length or 2) - 1
+ if e > 0 then
+ if pos >= b and pos <= e then
+ if spec then
+ spec[pos] = { s, k - 1 }
+ else
+ spec = { [pos] = { s, k - 1 } }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if trace_steps and done then
+ show_2(c,m,w,done,i,s)
+ end
+ end
+ end
+ end
+ if trace_steps and done then
+ show_3(w,done)
+ end
+ if done then
+ local okay = false
+ for i=3,#done do
+ if done[i] % 2 == 1 then
+ done[i-2] = spec and spec[i] or true
+ okay = true
+ else
+ done[i-2] = false
+ end
+ end
+ if okay then
+ done[#done] = nil
+ done[#done] = nil
+ else
+ done = false
+ end
+ else
+ done = false
+ end
+ hyphenated[key] = done
+ nofhashed = nofhashed + 1
+ return done
+end
+
+function traditional.gettrace(language,word)
+ if not word or word == "" then
+ return
+ end
+ local dictionary = dictionaries[language]
+ if dictionary then
+ local hyphenated = dictionary.hyphenated
+ hyphenated[word] = nil
+ hyphenate(dictionary,word)
+ return steps
+ end
+end
+
+local methods = setmetatableindex(function(t,k) local v = hyphenate t[k] = v return v end)
+
+function traditional.installmethod(name,f)
+ if rawget(methods,name) then
+ report("overloading %a is not permitted",name)
+ else
+ methods[name] = f
+ end
+end
+
+local s_detail_1 = "-"
+local f_detail_2 = formatters["%s-%s"]
+local f_detail_3 = formatters["{%s}{%s}{}"]
+local f_detail_4 = formatters["{%s%s}{%s%s}{%s}"]
+
+function traditional.injecthyphens(dictionary,word,specification)
+ if not word then
+ return false
+ end
+ if not specification then
+ return word
+ end
+ local hyphens = hyphenate(dictionary,word)
+ if not hyphens then
+ return word
+ end
+
+ -- the following code is similar to code later on but here we have strings while there
+ -- we have hyphen specs
+
+ local word = lpegmatch(p_split,word)
+ local size = #word
+
+ local leftmin = specification.leftcharmin or 2
+ local rightmin = size - (specification.rightcharmin or leftmin)
+ local leftchar = specification.leftchar
+ local rightchar = specification.rightchar
+
+ local result = { }
+ local rsize = 0
+ local position = 1
+
+ while position <= size do
+ if position >= leftmin and position <= rightmin then
+ local hyphen = hyphens[position]
+ if not hyphen then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ elseif hyphen == true then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ rsize = rsize + 1
+ if leftchar and rightchar then
+ result[rsize] = f_detail_3(rightchar,leftchar)
+ else
+ result[rsize] = s_detail_1
+ end
+ position = position + 1
+ else
+ local o, h = hyphen[2]
+ if o then
+ h = hyphen[1]
+ else
+ h = hyphen
+ o = 1
+ end
+ local b = position - o + (h.start or 1)
+ local e = b + (h.length or 2) - 1
+ if b > 0 and e >= b then
+ for i=1,b-position do
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ rsize = rsize + 1
+ if leftchar and rightchar then
+ result[rsize] = f_detail_4(h.before,rightchar,leftchar,h.after,concat(word,"",b,e))
+ else
+ result[rsize] = f_detail_2(h.before,h.after)
+ end
+ position = e + 1
+ else
+ -- error
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ else
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ return concat(result)
+end
+
+do
+
+ local word = C((1-space)^1)
+ local spaces = space^1
+
+ local u_pattern = (Carg(1) * Carg(2) * word / unregister_pattern + spaces)^1
+ local r_pattern = (Carg(1) * Carg(2) * word * Carg(3) / register_pattern + spaces)^1
+ local e_pattern = (Carg(1) * word / register_exception + spaces)^1
+
+ function traditional.registerpattern(language,str,specification)
+ local dictionary = dictionaries[language]
+ if specification == false then
+ lpegmatch(u_pattern,str,1,dictionary.patterns,dictionary.specials)
+ -- unregister_pattern(dictionary.patterns,dictionary.specials,str)
+ else
+ lpegmatch(r_pattern,str,1,dictionary.patterns,dictionary.specials,type(specification) == "table" and specification or false)
+ -- register_pattern(dictionary.patterns,dictionary.specials,str,specification)
+ end
+ end
+
+ function traditional.registerexception(language,str)
+ lpegmatch(e_pattern,str,1,dictionaries[language].exceptions)
+ end
+
+end
+
+-- todo: unicodes or utfhash ?
+
+if context then
+
+ local nodecodes = nodes.nodecodes
+ local disccodes = nodes.disccodes
+
+ local glyph_code = nodecodes.glyph
+ local disc_code = nodecodes.disc
+ local math_code = nodecodes.math
+ local hlist_code = nodecodes.hlist
+
+ local automaticdisc_code = disccodes.automatic
+ local regulardisc_code = disccodes.regular
+
+ local nuts = nodes.nuts
+ local tonode = nodes.tonode
+ local nodepool = nuts.pool
+
+ local new_disc = nodepool.disc
+ local new_penalty = nodepool.penalty
+
+ local getfield = nuts.getfield
+ local getfont = nuts.getfont
+ local getid = nuts.getid
+ local getattr = nuts.getattr
+ local getnext = nuts.getnext
+ local getprev = nuts.getprev
+ local getsubtype = nuts.getsubtype
+ local getlist = nuts.getlist
+ local getlanguage = nuts.getlanguage
+ local getattrlist = nuts.getattrlist
+ local setattrlist = nuts.setattrlist
+ local isglyph = nuts.isglyph
+ local ischar = nuts.ischar
+
+ local setchar = nuts.setchar
+ local setdisc = nuts.setdisc
+ local setlink = nuts.setlink
+ local setprev = nuts.setprev
+ local setnext = nuts.setnext
+
+ local insert_before = nuts.insert_before
+ local insert_after = nuts.insert_after
+ local copy_node = nuts.copy
+ local copy_list = nuts.copy_list
+ local remove_node = nuts.remove
+ local end_of_math = nuts.end_of_math
+ local node_tail = nuts.tail
+
+ local nexthlist = nuts.traversers.hlist
+ local nextdisc = nuts.traversers.disc
+
+ local setcolor = nodes.tracers.colors.set
+
+ local variables = interfaces.variables
+ local v_reset = variables.reset
+ local v_yes = variables.yes
+ local v_word = variables.word
+ local v_all = variables.all
+
+ local settings_to_array = utilities.parsers.settings_to_array
+
+ local unsetvalue = attributes.unsetvalue
+ local texsetattribute = tex.setattribute
+
+ local prehyphenchar = language.prehyphenchar
+ local posthyphenchar = language.posthyphenchar
+ local preexhyphenchar = language.preexhyphenchar
+ local postexhyphenchar = language.postexhyphenchar
+
+ local a_hyphenation = attributes.private("hyphenation")
+
+ local interwordpenalty = 5000
+
+ function traditional.loadpatterns(language)
+ return dictionaries[language]
+ end
+
+ -- for the moment we use an independent data structure
+
+ setmetatableindex(dictionaries,function(t,k)
+ if type(k) == "string" then
+ -- this will force a load if not yet loaded (we need a nicer way) for the moment
+ -- that will do (nneeded for examples that register a pattern specification
+ languages.getnumber(k)
+ end
+ local specification = languages.getdata(k)
+ local dictionary = {
+ patterns = { },
+ exceptions = { },
+ hyphenated = { },
+ specials = { },
+ instance = false,
+ characters = { },
+ unicodes = { },
+ }
+ if specification then
+ local resources = specification.resources
+ if resources then
+ local characters = dictionary.characters or { }
+ local unicodes = dictionary.unicodes or { }
+ for i=1,#resources do
+ local r = resources[i]
+ if not r.in_dictionary then
+ r.in_dictionary = true
+ local patterns = r.patterns
+ if patterns then
+ local data = patterns.data
+ if data then
+ -- regular patterns
+ lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials)
+ end
+ local extra = patterns.extra
+ if extra then
+ -- special patterns
+ lpegmatch(p_pattern,extra,1,dictionary.patterns,dictionary.specials)
+ end
+ end
+ local exceptions = r.exceptions
+ if exceptions then
+ local data = exceptions.data
+ if data and data ~= "" then
+ lpegmatch(p_exception,data,1,dictionary.exceptions)
+ end
+ end
+ local usedchars = lpegmatch(p_split,patterns.characters)
+ for i=1,#usedchars do
+ local char = usedchars[i]
+ local code = utfbyte(char)
+ local upper = uccodes[code]
+ characters[char] = code
+ unicodes [code] = char
+ if type(upper) == "table" then
+ for i=1,#upper do
+ local u = upper[i]
+ unicodes[u] = utfchar(u)
+ end
+ else
+ unicodes[upper] = utfchar(upper)
+ end
+ end
+ end
+ end
+ dictionary.characters = characters
+ dictionary.unicodes = unicodes
+ setmetatableindex(characters,function(t,k) local v = k and utfbyte(k) t[k] = v return v end)
+ end
+ t[specification.number] = dictionary
+ dictionary.instance = specification.instance -- needed for hyphenchars
+ end
+ t[k] = dictionary
+ return dictionary
+ end)
+
+ -- Beware: left and right min doesn't mean that in a 1 mmm hsize there can be snippets
+ -- with less characters than either of them! This could be an option but such a narrow
+ -- hsize doesn't make sense anyway.
+
+ -- We assume that featuresets are defined global ... local definitions (also mid paragraph)
+ -- make not much sense anyway. For the moment we assume no predefined sets so we don't need
+ -- to store them. Nor do we need to hash them in order to save space ... no sane user will
+ -- define many of them.
+
+ local featuresets = hyphenators.featuresets or { }
+ hyphenators.featuresets = featuresets
+
+ storage.shared.noflanguagesfeaturesets = storage.shared.noflanguagesfeaturesets or 0
+
+ local noffeaturesets = storage.shared.noflanguagesfeaturesets
+
+ storage.register("languages/hyphenators/featuresets",featuresets,"languages.hyphenators.featuresets")
+
+ ----- hash = table.sequenced(featureset,",") -- no need now
+
+ local function register(name,featureset)
+ noffeaturesets = noffeaturesets + 1
+ featureset.attribute = noffeaturesets
+ featuresets[noffeaturesets] = featureset -- access by attribute
+ featuresets[name] = featureset -- access by name
+ storage.shared.noflanguagesfeaturesets = noffeaturesets
+ return noffeaturesets
+ end
+
+ local function makeset(...)
+ -- a bit overkill, supporting variants but who cares
+ local set = { }
+ for i=1,select("#",...) do
+ local list = select(i,...)
+ local kind = type(list)
+ local used = nil
+ if kind == "string" then
+ if list == v_all then
+ -- not ok ... now all get ignored
+ return setmetatableindex(function(t,k) local v = utfchar(k) t[k] = v return v end)
+ elseif list ~= "" then
+ used = lpegmatch(p_split,list)
+ set = set or { }
+ for i=1,#used do
+ local char = used[i]
+ set[utfbyte(char)] = char
+ end
+ end
+ elseif kind == "table" then
+ if next(list) then
+ set = set or { }
+ for byte, char in next, list do
+ set[byte] = char == true and utfchar(byte) or char
+ end
+ elseif #list > 0 then
+ set = set or { }
+ for i=1,#list do
+ local l = list[i]
+ if type(l) == "number" then
+ set[l] = utfchar(l)
+ else
+ set[utfbyte(l)] = l
+ end
+ end
+ end
+ end
+ end
+ return set
+ end
+
+ -- category pd (tex also sees --- and -- as hyphens but do we really want that
+
+ local defaulthyphens = {
+ [0x002D] = true, -- HYPHEN-MINUS
+ [0x00AD] = 0x002D, -- SOFT HYPHEN (active in ConTeXt)
+ -- [0x058A] = true, -- ARMENIAN HYPHEN
+ -- [0x1400] = true, -- CANADIAN SYLLABICS HYPHEN
+ -- [0x1806] = true, -- MONGOLIAN TODO SOFT HYPHEN
+ [0x2010] = true, -- HYPHEN
+ -- [0x2011] = true, -- NON-BREAKING HYPHEN
+ -- [0x2012] = true, -- FIGURE DASH
+ [0x2013] = true, -- EN DASH
+ [0x2014] = true, -- EM DASH
+ -- [0x2015] = true, -- HORIZONTAL BAR
+ -- [0x2027] = true, -- HYPHENATION POINT
+ -- [0x2E17] = true, -- DOUBLE OBLIQUE HYPHEN
+ -- [0x2E1A] = true, -- HYPHEN WITH DIAERESIS
+ -- [0x2E3A] = true, -- TWO-EM DASH
+ -- [0x2E3B] = true, -- THREE-EM DASH
+ -- [0x2E40] = true, -- DOUBLE HYPHEN
+ -- [0x301C] = true, -- WAVE DASH
+ -- [0x3030] = true, -- WAVY DASH
+ -- [0x30A0] = true, -- KATAKANA-HIRAGANA DOUBLE HYPHEN
+ -- [0xFE31] = true, -- PRESENTATION FORM FOR VERTICAL EM DASH
+ -- [0xFE32] = true, -- PRESENTATION FORM FOR VERTICAL EN DASH
+ -- [0xFE58] = true, -- SMALL EM DASH
+ -- [0xFE63] = true, -- SMALL HYPHEN-MINUS
+ -- [0xFF0D] = true, -- FULLWIDTH HYPHEN-MINUS
+ }
+
+ local defaultjoiners = {
+ [0x200C] = true, -- nzwj
+ [0x200D] = true, -- zwj
+ }
+
+ local function somehyphenchar(c)
+ c = tonumber(c)
+ return c ~= 0 and c or nil
+ end
+
+ local function definefeatures(name,featureset)
+ local extrachars = featureset.characters -- "[]()"
+ local hyphenchars = featureset.hyphens
+ local joinerchars = featureset.joiners
+ local alternative = featureset.alternative
+ local rightwordmin = tonumber(featureset.rightwordmin)
+ local charmin = tonumber(featureset.charmin) -- luatex now also has hyphenationmin
+ local leftcharmin = tonumber(featureset.leftcharmin)
+ local rightcharmin = tonumber(featureset.rightcharmin)
+ local leftchar = somehyphenchar(featureset.leftchar)
+ local rightchar = somehyphenchar(featureset.rightchar)
+ local rightchars = featureset.rightchars
+local rightedge = featureset.rightedge
+local autohyphen = v_yes -- featureset.autohyphen -- insert disc
+local hyphenonly = v_yes -- featureset.hyphenonly -- don't hyphenate around
+ rightchars = rightchars == v_word and true or tonumber(rightchars)
+ joinerchars = joinerchars == v_yes and defaultjoiners or joinerchars -- table
+ hyphenchars = hyphenchars == v_yes and defaulthyphens or hyphenchars -- table
+ -- not yet ok: extrachars have to be ignored so it cannot be all)
+ featureset.extrachars = makeset(joinerchars or "",extrachars or "")
+ featureset.hyphenchars = makeset(hyphenchars or "")
+ featureset.alternative = alternative or "hyphenate"
+ featureset.rightwordmin = rightwordmin and rightwordmin > 0 and rightwordmin or nil
+ featureset.charmin = charmin and charmin > 0 and charmin or nil
+ featureset.leftcharmin = leftcharmin and leftcharmin > 0 and leftcharmin or nil
+ featureset.rightcharmin = rightcharmin and rightcharmin > 0 and rightcharmin or nil
+ featureset.rightchars = rightchars
+ featureset.leftchar = leftchar
+ featureset.rightchar = rightchar
+ -- featureset.strict = rightedge == "tex"
+featureset.autohyphen = autohyphen == v_yes
+featureset.hyphenonly = hyphenonly == v_yes
+ return register(name,featureset)
+ end
+
+ local function setfeatures(n)
+ if not n or n == v_reset then
+ n = false
+ else
+ local f = featuresets[n]
+ if not f and type(n) == "string" then
+ local t = settings_to_array(n)
+ local s = { }
+ for i=1,#t do
+ local ti = t[i]
+ local fs = featuresets[ti]
+ if fs then
+ for k, v in next, fs do
+ s[k] = v
+ end
+ end
+ end
+ n = register(n,s)
+ else
+ n = f and f.attribute
+ end
+ end
+ texsetattribute(a_hyphenation,n or unsetvalue)
+ end
+
+ traditional.definefeatures = definefeatures
+ traditional.setfeatures = setfeatures
+
+ implement {
+ name = "definehyphenationfeatures",
+ actions = definefeatures,
+ arguments = {
+ "string",
+ {
+ { "characters" },
+ { "hyphens" },
+ { "joiners" },
+ { "rightchars" },
+ { "rightwordmin", "integer" },
+ { "charmin", "integer" },
+ { "leftcharmin", "integer" },
+ { "rightcharmin", "integer" },
+ { "leftchar", "integer" },
+ { "rightchar", "integer" },
+ { "alternative" },
+ { "rightedge" },
+ }
+ }
+ }
+
+ implement {
+ name = "sethyphenationfeatures",
+ actions = setfeatures,
+ arguments = "string"
+ }
+
+ implement {
+ name = "registerhyphenationpattern",
+ actions = traditional.registerpattern,
+ arguments = { "string", "string", "boolean" }
+ }
+
+ implement {
+ name = "registerhyphenationexception",
+ actions = traditional.registerexception,
+ arguments = "2 strings",
+ }
+
+ -- This is a relative large function with local variables and local functions. A previous
+ -- implementation had the functions outside but this is cleaner and as efficient. The test
+ -- runs 100 times over tufte.tex, knuth.tex, zapf.tex, ward.tex and darwin.tex in lower
+ -- and uppercase with a 1mm hsize.
+ --
+ -- language=0 language>0 4 | 3 * slower
+ --
+ -- tex 2.34 | 1.30 2.55 | 1.45 0.21 | 0.15
+ -- lua 2.42 | 1.38 3.30 | 1.84 0.88 | 0.46
+ --
+ -- Of course we have extra overhead (virtual Lua machine) but also we check attributes and
+ -- support specific local options). The test puts the typeset text in boxes and discards
+ -- it. If we also flush the runtime is 4.31|2.56 and 4.99|2.94 seconds so the relative
+ -- difference is (somehow) smaller. The test has 536 pages. There is a little bit of extra
+ -- overhead because we store the patterns in a different way.
+ --
+ -- As usual I will look for speedups. Some 0.01 seconds could be gained by sharing patterns
+ -- which is not impressive but it does save some 3M memory on this test. (Some optimizations
+ -- already brought the 3.30 seconds down to 3.14 but it all depends on aggressive caching.)
+
+ -- As we kick in the hyphenator before fonts get handled, we don't look at implicit (font)
+ -- kerns or ligatures.
+
+ local starttiming = statistics.starttiming
+ local stoptiming = statistics.stoptiming
+
+ -- local strictids = {
+ -- [nodecodes.hlist] = true,
+ -- [nodecodes.vlist] = true,
+ -- [nodecodes.rule] = true,
+ -- [nodecodes.dir] = true,
+ -- [nodecodes.whatsit] = true,
+ -- [nodecodes.ins] = true,
+ -- [nodecodes.adjust] = true,
+ --
+ -- [nodecodes.math] = true,
+ -- [nodecodes.disc] = true,
+ --
+ -- [nodecodes.accent] = true, -- never used in context
+ -- }
+
+ -- a lot of overhead when only one char
+
+ function traditional.hyphenate(head)
+
+ local first = head
+ local tail = nil
+ local last = nil
+ local current = first
+ local dictionary = nil
+ local instance = nil
+ local characters = nil
+ local unicodes = nil
+ local exhyphenchar = tex.exhyphenchar
+ local extrachars = nil
+ local hyphenchars = nil
+ local language = nil
+ local lastfont = nil
+ local start = nil
+ local stop = nil
+ local word = { } -- we reuse this table
+ local size = 0
+ local leftchar = false
+ local rightchar = false -- utfbyte("-")
+ local leftexchar = false
+ local rightexchar = false -- utfbyte("-")
+ local leftmin = 0
+ local rightmin = 0
+ local charmin = 1
+ local leftcharmin = nil
+ local rightcharmin = nil
+ ----- leftwordmin = nil
+ local rightwordmin = nil
+ local rightchars = nil
+ local leftchar = nil
+ local rightchar = nil
+ local attr = nil
+ local lastwordlast = nil
+ local hyphenated = hyphenate
+ ----- strict = nil
+ local exhyphenpenalty = tex.exhyphenpenalty
+ local hyphenpenalty = tex.hyphenpenalty
+ local autohyphen = false
+ local hyphenonly = false
+
+ -- We cannot use an 'enabled' boolean (false when no characters or extras) because we
+ -- can have plugins that set a characters metatable and so) ... it doesn't save much
+ -- anyway. Using (unicodes and unicodes[code]) and a nil table when no characters also
+ -- doesn't save much. So there not that much to gain for languages that don't hyphenate.
+ --
+ -- enabled = (unicodes and (next(unicodes) or getmetatable(unicodes)))
+ -- or (extrachars and next(extrachars))
+ --
+ -- This can be used to not add characters i.e. keep size 0 but then we need to check for
+ -- attributes that change it, which costs time too. Not much to gain there.
+
+ starttiming(traditional)
+
+ local function insertpenalty()
+ local p = new_penalty(interwordpenalty)
+ setattrlist(p,last)
+ if trace_visualize then
+ nuts.setvisual(p,"penalty")
+ end
+ last = getprev(last)
+ first, last = insert_after(first,last,p)
+ end
+
+ local function synchronizefeatureset(a)
+ local f = a and featuresets[a]
+ if f then
+ hyphenated = methods[f.alternative or "hyphenate"]
+ extrachars = f.extrachars
+ hyphenchars = f.hyphenchars
+ rightwordmin = f.rightwordmin
+ charmin = f.charmin
+ leftcharmin = f.leftcharmin
+ rightcharmin = f.rightcharmin
+ leftchar = f.leftchar
+ rightchar = f.rightchar
+ -- strict = f.strict and strictids
+ rightchars = f.rightchars
+ autohyphen = f.autohyphen
+ hyphenonly = f.hyphenonly
+ if rightwordmin and rightwordmin > 0 and lastwordlast ~= rightwordmin then
+ -- so we can change mid paragraph but it's kind of unpredictable then
+ if not tail then
+ tail = node_tail(first)
+ end
+ last = tail
+ local inword = false
+ local count = 0
+ while last and rightwordmin > 0 do
+ local id = getid(last)
+ if id == glyph_code then
+ count = count + 1
+ inword = true
+ if trace_visualize then
+ setcolor(last,"darkgreen")
+ end
+ elseif inword then
+ inword = false
+ rightwordmin = rightwordmin - 1
+ if rightchars == true then
+ if rightwordmin > 0 then
+ insertpenalty()
+ end
+ elseif rightchars and count <= rightchars then
+ insertpenalty()
+ end
+ end
+ last = getprev(last)
+ end
+ lastwordlast = rightwordmin
+ end
+ if not charmin or charmin == 0 then
+ charmin = 1
+ end
+ else
+ hyphenated = methods.hyphenate
+ extrachars = false
+ hyphenchars = false
+ rightwordmin = false
+ charmin = 1
+ leftcharmin = false
+ rightcharmin = false
+ leftchar = false
+ rightchar = false
+ -- strict = false
+ autohyphen = false
+ hyphenonly = false
+ end
+
+ return a
+ end
+
+ local function flush(hyphens) -- todo: no need for result
+
+ local rightmin = size - rightmin
+ local result = { }
+ local rsize = 0
+ local position = 1
+
+ -- todo: remember last dics and don't go back to before that (plus message) ...
+ -- for simplicity we also assume that we don't start with a dics node
+ --
+ -- there can be a conflict: if we backtrack then we can end up in another disc
+ -- and get out of sync (dup chars and so)
+
+ while position <= size do
+ if position >= leftmin and position <= rightmin then
+ local hyphen = hyphens[position]
+ if not hyphen then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ elseif hyphen == true then
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ rsize = rsize + 1
+ result[rsize] = true
+ position = position + 1
+ else
+ local o, h = hyphen[2]
+ if o then
+ -- { hyphen, offset)
+ h = hyphen[1]
+ else
+ -- hyphen
+ h = hyphen
+ o = 1
+ end
+ local b = position - o + (h.start or 1)
+ local e = b + (h.length or 2) - 1
+ if b > 0 and e >= b then
+ for i=1,b-position do
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ rsize = rsize + 1
+ result[rsize] = {
+ h.before or "", -- pre
+ h.after or "", -- post
+ concat(word,"",b,e), -- replace
+ h.right, -- optional after pre
+ h.left, -- optional before post
+ }
+ position = e + 1
+ else
+ -- error
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+ else
+ rsize = rsize + 1
+ result[rsize] = word[position]
+ position = position + 1
+ end
+ end
+
+ local function serialize(replacement,leftchar,rightchar)
+ if not replacement then
+ return
+ elseif replacement == true then
+ local glyph = copy_node(stop)
+ setchar(glyph,leftchar or rightchar)
+ return glyph
+ end
+ local head = nil
+ local current = nil
+ if leftchar then
+ head = copy_node(stop)
+ current = head
+ setchar(head,leftchar)
+ end
+ local rsize = #replacement
+ if rsize == 1 then
+ local glyph = copy_node(stop)
+ setchar(glyph,characters[replacement])
+ if head then
+ insert_after(current,current,glyph)
+ else
+ head = glyph
+ end
+ current = glyph
+ elseif rsize > 0 then
+ local list = lpegmatch(p_split,replacement) -- this is an utf split (could be cached)
+ for i=1,#list do
+ local glyph = copy_node(stop)
+ setchar(glyph,characters[list[i]])
+ if head then
+ insert_after(current,current,glyph)
+ else
+ head = glyph
+ end
+ current = glyph
+ end
+ end
+ if rightchar then
+ local glyph = copy_node(stop)
+ insert_after(current,current,glyph)
+ setchar(glyph,rightchar)
+ end
+ return head
+ end
+
+ local current = start
+ local attrnode = start -- will be different, just the first char
+
+ for i=1,rsize do
+ local r = result[i]
+ if r == true then
+ local disc = new_disc()
+ local pre = nil
+ local post = nil
+ if rightchar then
+ pre = serialize(true,rightchar)
+ end
+ if leftchar then
+ post = serialize(true,leftchar)
+ end
+ setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty)
+ if attrnode then
+ setattrlist(disc,attrnode)
+ end
+ -- could be a replace as well
+ insert_before(first,current,disc)
+ elseif type(r) == "table" then
+ local disc = new_disc()
+ local pre = r[1]
+ local post = r[2]
+ local replace = r[3]
+ local right = r[4] ~= false and rightchar
+ local left = r[5] ~= false and leftchar
+ if pre then
+ if pre ~= "" then
+ pre = serialize(pre,false,right)
+ else
+ pre = nil
+ end
+ end
+ if post then
+ if post ~= "" then
+ post = serialize(post,left,false)
+ else
+ post = nil
+ end
+ end
+ if replace then
+ if replace ~= "" then
+ replace = serialize(replace)
+ else
+ replace = nil
+ end
+ end
+ -- maybe regular code
+ setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty)
+ if attrnode then
+ setattrlist(disc,attrnode)
+ end
+ insert_before(first,current,disc)
+ else
+ setchar(current,characters[r])
+ if i < rsize then
+ current = getnext(current)
+ end
+ end
+ end
+ if current and current ~= stop then
+ local current = getnext(current)
+ local last = getnext(stop)
+ while current ~= last do
+ first, current = remove_node(first,current,true)
+ end
+ end
+
+ end
+
+ local function inject(leftchar,rightchar,code,attrnode)
+ if first ~= current then
+ local disc = new_disc()
+ first, current, glyph = remove_node(first,current)
+ first, current = insert_before(first,current,disc)
+ if trace_visualize then
+ setcolor(glyph,"darkred") -- these get checked
+ setcolor(disc,"darkgreen") -- in the colorizer
+ end
+ local pre = nil
+ local post = nil
+ local replace = glyph
+ if leftchar and leftchar > 0 then
+ post = copy_node(glyph)
+ setchar(post,leftchar)
+ end
+ pre = copy_node(glyph)
+ setchar(pre,rightchar and rightchar > 0 and rightchar or code)
+ setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ?
+ if attrnode then
+ setattrlist(disc,attrnode)
+ end
+ end
+ return current
+ end
+
+ local function injectseries(current,last,next,attrnode)
+ local disc = new_disc()
+ local start = current
+ first, current = insert_before(first,current,disc)
+ setprev(start)
+ setnext(last)
+ if next then
+ setlink(current,next)
+ else
+ setnext(current)
+ end
+ local pre = copy_list(start)
+ local post = nil
+ local replace = start
+ setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ?
+ if attrnode then
+ setattrlist(disc,attrnode)
+ end
+ return current
+ end
+
+ local a = getattr(first,a_hyphenation)
+ if a ~= attr then
+ attr = synchronizefeatureset(a)
+ end
+
+ -- The first attribute in a word determines the way a word gets hyphenated and if
+ -- relevant, other properties are also set then. We could optimize for silly one-char
+ -- cases but it has no priority as the code is still not that much slower than the
+ -- native hyphenator and this variant also provides room for extensions.
+
+ local skipping = false
+
+ -- In "word word word." the sequences "word" and "." can be a different font!
+
+ while current and current ~= last do -- and current
+ local code, id = isglyph(current)
+ if code then
+ if skipping then
+ current = getnext(current)
+ else
+ local lang = getlanguage(current)
+ local font = getfont(current)
+ if lang ~= language or font ~= lastfont then
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ -- only german has many words starting with an uppercase character
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ lastfont = font
+ if language ~= lang and lang > 0 then
+ --
+ dictionary = dictionaries[lang]
+ instance = dictionary.instance
+ characters = dictionary.characters
+ unicodes = dictionary.unicodes
+ --
+ local a = getattr(current,a_hyphenation)
+ attr = synchronizefeatureset(a)
+ leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more
+ rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed
+ leftexchar = (instance and preexhyphenchar (instance))
+ rightexchar = (instance and postexhyphenchar(instance))
+ leftmin = leftcharmin or getfield(current,"left")
+ rightmin = rightcharmin or getfield(current,"right")
+ if not leftchar or leftchar < 0 then
+ leftchar = false
+ end
+ if not rightchar or rightchar < 0 then
+ rightchar = false
+ end
+ --
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ word[1] = char
+ size = 1
+ start = current
+ else
+ size = 0
+ end
+ else
+ size = 0
+ end
+ language = lang
+ elseif language <= 0 then
+ --
+ elseif size > 0 then
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ size = size + 1
+ word[size] = char
+ elseif dictionary then
+ if not hyphenonly or code ~= exhyphenchar then
+ if size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ end
+ size = 0
+ if code == exhyphenchar then -- normally the -
+ local next = getnext(current)
+ local last = current
+ local font = getfont(current)
+ while next and ischar(next,font) == code do
+ last = next
+ next = getnext(next)
+ end
+ if not autohyphen then
+ current = last
+ elseif current == last then
+ current = inject(leftexchar,rightexchar,code,current)
+ else
+ current = injectseries(current,last,next,current)
+ end
+ if hyphenonly then
+ skipping = true
+ end
+ elseif hyphenchars then
+ local char = hyphenchars[code]
+ if char == true then
+ char = code
+ end
+ if char then
+ current = inject(leftchar and char or nil,rightchar and char or nil,char,current)
+ end
+ end
+ end
+ else
+ local a = getattr(current,a_hyphenation)
+ if a ~= attr then
+ attr = synchronizefeatureset(a) -- influences extrachars
+ leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more
+ rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed
+ leftexchar = (instance and preexhyphenchar (instance))
+ rightexchar = (instance and postexhyphenchar(instance))
+ leftmin = leftcharmin or getfield(current,"left")
+ rightmin = rightcharmin or getfield(current,"right")
+ if not leftchar or leftchar < 0 then
+ leftchar = false
+ end
+ if not rightchar or rightchar < 0 then
+ rightchar = false
+ end
+ end
+ --
+ local char = unicodes[code] or (extrachars and extrachars[code])
+ if char then
+ word[1] = char
+ size = 1
+ start = current
+ end
+ end
+ stop = current
+ current = getnext(current)
+ end
+ else
+ if skipping then
+ skipping = false
+ end
+ if id == disc_code then
+ size = 0
+ current = getnext(current)
+ if hyphenonly then
+ skipping = true
+ end
+ -- elseif strict and strict[id] then
+ -- current = id == math_code and getnext(end_of_math(current)) or getnext(current)
+ -- size = 0
+ else
+ current = id == math_code and getnext(end_of_math(current)) or getnext(current)
+ end
+ if size > 0 then
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+ size = 0
+ end
+ end
+ end
+ -- we can have quit due to last so we need to flush the last seen word, we could move
+ -- this in the loop and test for current but ... messy
+ if dictionary and size > charmin and leftmin + rightmin <= size then
+ if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
+ -- skip
+ else
+ local hyphens = hyphenated(dictionary,word,size)
+ if hyphens then
+ flush(hyphens)
+ end
+ end
+ end
+
+ stoptiming(traditional)
+
+ return head
+ end
+
+ statistics.register("hyphenation",function()
+ if nofwords > 0 or statistics.elapsed(traditional) > 0 then
+ return string.format("%s words hyphenated, %s unique, used time %s",
+ nofwords,nofhashed,statistics.elapsedseconds(traditional) or 0)
+ end
+ end)
+
+ local texmethod = "builders.kernel.hyphenation"
+ local oldmethod = texmethod
+ local newmethod = texmethod
+
+ -- local newmethod = "languages.hyphenators.traditional.hyphenate"
+ --
+ -- nodes.tasks.prependaction("processors","words",newmethod)
+ -- nodes.tasks.disableaction("processors",oldmethod)
+ --
+ -- nodes.tasks.replaceaction("processors","words",oldmethod,newmethod)
+
+ -- \enabledirectives[hyphenators.method=traditional]
+ -- \enabledirectives[hyphenators.method=builtin]
+
+ -- push / pop ? check first attribute
+
+ -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches)
+
+ local hyphenate = language.hyphenate
+ local hyphenating = nuts.hyphenating
+ local methods = { }
+ local usedmethod = false
+ local stack = { }
+
+ local original = hyphenating and
+ function(head)
+ return (hyphenating(head))
+ end
+ or
+ function(head)
+ hyphenate(tonode(head))
+ return head -- a nut
+ end
+
+ -- local has_language = language.has_language
+ --
+ -- local function original(head) -- kernel.hyphenation(head)
+ -- local h = tonode(head)
+ -- if has_language(h) then
+ -- hyphenate(h)
+ -- end
+ -- return head
+ -- end
+
+ local getcount = tex.getcount
+
+ hyphenators.methods = methods
+ local optimize = false
+
+ directives.register("hyphenator.optimize", function(v) optimize = v end)
+
+ function hyphenators.handler(head,groupcode)
+ if usedmethod then
+ if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then
+ if getcount("hyphenstate") > 0 then
+ forced = false
+ return usedmethod(head)
+ else
+ return head
+ end
+ else
+ return usedmethod(head)
+ end
+ else
+ return head
+ end
+ end
+
+ methods.tex = original
+ methods.original = original
+ methods.expanded = original -- was expanded before 1.005
+ methods.traditional = languages.hyphenators.traditional.hyphenate
+ methods.none = false -- function(head) return head, false end
+
+ usedmethod = original
+
+ local function setmethod(method)
+ usedmethod = type(method) == "string" and methods[method]
+ if usedmethod == nil then
+ usedmethod = methods.tex
+ end
+ end
+ local function pushmethod(method)
+ insert(stack,usedmethod)
+ usedmethod = type(method) == "string" and methods[method]
+ if usedmethod == nil then
+ usedmethod = methods.tex
+ end
+ end
+ local function popmethod()
+ usedmethod = remove(stack) or methods.tex
+ end
+
+ hyphenators.setmethod = setmethod
+ hyphenators.pushmethod = pushmethod
+ hyphenators.popmethod = popmethod
+
+ directives.register("hyphenators.method",setmethod)
+
+ function hyphenators.setup(specification)
+ local method = specification.method
+ if method then
+ setmethod(method)
+ end
+ end
+
+ implement { name = "sethyphenationmethod", actions = setmethod, arguments = "string" }
+ implement { name = "pushhyphenation", actions = pushmethod, arguments = "string" }
+ implement { name = "pophyphenation", actions = popmethod }
+
+ -- can become a runtime loaded one:
+
+ local context = context
+ local ctx_NC = context.NC
+ local ctx_NR = context.NR
+ local ctx_verbatim = context.verbatim
+
+ function hyphenators.showhyphenationtrace(language,word)
+ if not word or word == "" then
+ return
+ end
+ local saved = trace_steps
+ trace_steps = "silent"
+ local steps = traditional.gettrace(language,word)
+ trace_steps = saved
+ if steps then
+ local n = #steps
+ if n > 0 then
+ context.starttabulate { "|r|l|l|l|" }
+ for i=1,n do
+ local s = steps[i]
+ ctx_NC() if i > 1 and i < n then context(i-1) end
+ ctx_NC() ctx_verbatim(s[1])
+ ctx_NC() ctx_verbatim(s[2])
+ ctx_NC() ctx_verbatim(s[3])
+ ctx_NC()
+ ctx_NR()
+ end
+ context.stoptabulate()
+ end
+ end
+ end
+
+ implement {
+ name = "showhyphenationtrace",
+ actions = hyphenators.showhyphenationtrace,
+ arguments = "2 strings",
+ }
+
+ function nodes.stripdiscretionaries(head)
+ for l in nexthlist, head do
+ for d in nextdisc, getlist(l) do
+ remove_node(h,false,true)
+ end
+ end
+ return head
+ end
+
+
+else
+
+ -- traditional.loadpatterns("nl","lang-nl")
+ -- traditional.loadpatterns("de","lang-de")
+ -- traditional.loadpatterns("us","lang-us")
+
+ -- traditional.registerpattern("nl","e1ë", { start = 1, length = 2, before = "e", after = "e" } )
+ -- traditional.registerpattern("nl","oo7ë", { start = 2, length = 3, before = "o", after = "e" } )
+ -- traditional.registerpattern("de","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } )
+
+ -- local specification = {
+ -- leftcharmin = 2,
+ -- rightcharmin = 2,
+ -- leftchar = "<",
+ -- rightchar = ">",
+ -- }
+
+ -- print("reëel", traditional.injecthyphens(dictionaries.nl,"reëel", specification),"r{e>}{<e}{eë}el")
+ -- print("reeëel", traditional.injecthyphens(dictionaries.nl,"reeëel", specification),"re{e>}{<e}{eë}el")
+ -- print("rooëel", traditional.injecthyphens(dictionaries.nl,"rooëel", specification),"r{o>}{<e}{ooë}el")
+
+ -- print( "qxcxkq", traditional.injecthyphens(dictionaries.de, "qxcxkq", specification),"")
+ -- print( "qqxcxkqq", traditional.injecthyphens(dictionaries.de, "qqxcxkqq", specification),"")
+ -- print( "qqqxcxkqqq", traditional.injecthyphens(dictionaries.de, "qqqxcxkqqq", specification),"")
+ -- print("qqqqxcxkqqqq",traditional.injecthyphens(dictionaries.de,"qqqqxcxkqqqq",specification),"")
+
+ -- print("kunstmatig", traditional.injecthyphens(dictionaries.nl,"kunstmatig", specification),"")
+ -- print("kunststofmatig", traditional.injecthyphens(dictionaries.nl,"kunststofmatig", specification),"")
+ -- print("kunst[stof]matig", traditional.injecthyphens(dictionaries.nl,"kunst[stof]matig", specification),"")
+
+ -- traditional.loadpatterns("us","lang-us")
+
+ -- local specification = {
+ -- leftcharmin = 2,
+ -- rightcharmin = 2,
+ -- leftchar = false,
+ -- rightchar = false,
+ -- }
+
+ -- trace_steps = true
+
+ -- print("components", traditional.injecthyphens(dictionaries.us,"components", specification),"")
+ -- print("single", traditional.injecthyphens(dictionaries.us,"single", specification),"sin-gle")
+ -- print("everyday", traditional.injecthyphens(dictionaries.us,"everyday", specification),"every-day")
+ -- print("associate", traditional.injecthyphens(dictionaries.us,"associate", specification),"as-so-ciate")
+ -- print("philanthropic", traditional.injecthyphens(dictionaries.us,"philanthropic", specification),"phil-an-thropic")
+ -- print("projects", traditional.injecthyphens(dictionaries.us,"projects", specification),"projects")
+ -- print("Associate", traditional.injecthyphens(dictionaries.us,"Associate", specification),"As-so-ciate")
+ -- print("Philanthropic", traditional.injecthyphens(dictionaries.us,"Philanthropic", specification),"Phil-an-thropic")
+ -- print("Projects", traditional.injecthyphens(dictionaries.us,"Projects", specification),"Projects")
+
+end
+
diff --git a/tex/context/base/mkiv/lang-hyp.lua b/tex/context/base/mkiv/lang-hyp.lua
index 93457c7a2..ca9f519ce 100644
--- a/tex/context/base/mkiv/lang-hyp.lua
+++ b/tex/context/base/mkiv/lang-hyp.lua
@@ -644,7 +644,7 @@ if context then
local getprev = nuts.getprev
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
- local getlang = nuts.getlang
+ local getlanguage = nuts.getlanguage
local getattrlist = nuts.getattrlist
local setattrlist = nuts.setattrlist
local isglyph = nuts.isglyph
@@ -1410,7 +1410,7 @@ featureset.hyphenonly = hyphenonly == v_yes
if skipping then
current = getnext(current)
else
- local lang = getlang(current)
+ local lang = getlanguage(current)
local font = getfont(current)
if lang ~= language or font ~= lastfont then
if dictionary and size > charmin and leftmin + rightmin <= size then
diff --git a/tex/context/base/mkiv/lang-hyp.mkiv b/tex/context/base/mkiv/lang-hyp.mkiv
index fbd83fe0c..d8fbb0b22 100644
--- a/tex/context/base/mkiv/lang-hyp.mkiv
+++ b/tex/context/base/mkiv/lang-hyp.mkiv
@@ -30,8 +30,8 @@
\writestatus{loading}{ConTeXt Language Macros / Initialization}
-\registerctxluafile{lang-dis}{}
-\registerctxluafile{lang-hyp}{}
+\registerctxluafile{lang-dis}{autosuffix}
+\registerctxluafile{lang-hyp}{autosuffix}
\unprotect
@@ -152,7 +152,7 @@ rightedge {\dummyparameter\c!rightedge}%
{\clf_sethyphenationfeatures{#1}}
\unexpanded\def\resethyphenationfeatures
- {\hyphenationattribute\attributeunsetvalue}
+ {\attribute\hyphenationattribute\attributeunsetvalue}
\resethyphenationfeatures
diff --git a/tex/context/base/mkiv/lang-ini.lmt b/tex/context/base/mkiv/lang-ini.lmt
new file mode 100644
index 000000000..5f2dd1a55
--- /dev/null
+++ b/tex/context/base/mkiv/lang-ini.lmt
@@ -0,0 +1,670 @@
+if not modules then modules = { } end modules ['lang-ini'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- needs a cleanup (share locals)
+-- discard language when redefined
+
+-- 002D : hyphen-minus (ascii)
+-- 2010 : hyphen
+-- 2011 : nonbreakable hyphen
+-- 2013 : endash (compound hyphen)
+
+--~ language:hyphenation(string) string = language:hyphenation() language:clear_hyphenation()
+
+-- todo: no foo:bar but foo(bar,...)
+
+local type, tonumber, next = type, tonumber, next
+local utfbyte = utf.byte
+local format, gsub, gmatch, find = string.format, string.gsub, string.gmatch, string.find
+local concat, sortedkeys, sortedpairs, keys, insert = table.concat, table.sortedkeys, table.sortedpairs, table.keys, table.insert
+local utfvalues, strip, utfcharacters = string.utfvalues, string.strip, utf.characters
+
+local context = context
+local commands = commands
+local implement = interfaces.implement
+
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_set = utilities.parsers.settings_to_set
+
+local trace_patterns = false trackers.register("languages.patterns", function(v) trace_patterns = v end)
+
+local report_initialization = logs.reporter("languages","initialization")
+
+local prehyphenchar = language.prehyphenchar -- global per language
+local posthyphenchar = language.posthyphenchar -- global per language
+local preexhyphenchar = language.preexhyphenchar -- global per language
+local postexhyphenchar = language.postexhyphenchar -- global per language
+----- lefthyphenmin = language.lefthyphenmin
+----- righthyphenmin = language.righthyphenmin
+local sethjcode = language.sethjcode
+local currentlanguage = language.current -- or function() return tex.normallanguage or tex.language end
+
+local uccodes = characters.uccodes
+local lccodes = characters.lccodes
+
+local new_language = language.new
+
+languages = languages or {}
+local languages = languages
+
+languages.version = 1.010
+
+languages.registered = languages.registered or { }
+local registered = languages.registered
+
+languages.associated = languages.associated or { }
+local associated = languages.associated
+
+languages.numbers = languages.numbers or { }
+local numbers = languages.numbers
+
+languages.data = languages.data or { }
+local data = languages.data
+
+storage.register("languages/registered",registered,"languages.registered")
+storage.register("languages/associated",associated,"languages.associated")
+storage.register("languages/numbers", numbers, "languages.numbers")
+storage.register("languages/data", data, "languages.data")
+
+local variables = interfaces.variables
+
+local v_reset = variables.reset
+local v_yes = variables.yes
+
+local nofloaded = 0
+
+local function resolve(tag)
+ local data, instance = registered[tag], nil
+ if data then
+ instance = data.instance
+ if not instance then
+ instance = new_language(data.number)
+ data.instance = instance
+ end
+ end
+ return data, instance
+end
+
+local function tolang(what) -- returns lang object
+ if not what then
+ what = currentlanguage()
+ end
+ local tag = numbers[what]
+ local data = tag and registered[tag] or registered[what]
+ if data then
+ local instance = data.instance -- .lang -- was this ok ?
+ if not instance then
+ instance = new_language(data.number)
+ data.instance = instance
+ end
+ return instance
+ end
+end
+
+function languages.getdata(tag) -- or number
+ if tag then
+ return registered[tag] or registered[numbers[tag]]
+ else
+ return registered[numbers[currentlanguage()]]
+ end
+end
+
+-- languages.tolang = tolang
+
+-- patterns=en
+-- patterns=en,de
+
+local function validdata(loaded,what,tag)
+ local dataset = loaded[what]
+ if dataset then
+ local data = dataset.data
+ if not data or data == "" then
+ -- nothing
+ elseif dataset.compression == "zlib" then
+ data = zlib.decompress(data)
+ if dataset.length and dataset.length ~= #data then
+ report_initialization("compression error in %a for language %a","patterns",what,tag)
+ end
+ return data
+ else
+ return data
+ end
+ end
+end
+
+-- languages.hjcounts[unicode].count
+
+-- hjcode: 0 not to be hyphenated
+-- 1--31 length
+-- 32 zero length
+-- > 32 hyphenated with length 1
+
+local function sethjcodes(instance,loaded,what,factor)
+ local l = loaded[what]
+ local c = l and l.characters
+ if c then
+ local hjcounts = factor and languages.hjcounts or false
+ --
+ local h = loaded.codehash
+ if not h then
+ h = { }
+ loaded.codehash = h
+ end
+ --
+ local function setcode(l)
+ local u = uccodes[l]
+ local s = l
+ if hjcounts then
+ local c = hjcounts[l]
+ if c then
+ c = c.count
+ if not c then
+ -- error, keep as 1
+ elseif c <= 0 then
+ -- counts as 0 i.e. ignored
+ s = 32
+ elseif c >= 31 then
+ -- counts as 31
+ s = 31
+ else
+ -- count c times
+ s = c
+ end
+ end
+ end
+ sethjcode(instance,l,s)
+ h[l] = s
+ if u ~= l and type(u) == "number" then
+ sethjcode(instance,u,s)
+ h[u] = lccodes[l]
+ end
+ end
+ --
+ local s = tex.savinghyphcodes
+ tex.savinghyphcodes = 0
+ if type(c) == "table" then
+ for l in next, c do
+ setcode(utfbyte(l))
+ end
+ else
+ for l in utfvalues(c) do
+ setcode(l)
+ end
+ end
+ tex.savinghyphcodes = s
+ end
+end
+
+-- 2'2 conflicts with 4' ... and luatex barks on it
+
+local P, R, Cs, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.match, lpeg.patterns
+
+local utfsplit = utf.split
+
+local space = lpegpatterns.space
+local whitespace = lpegpatterns.whitespace^1
+local nospace = lpegpatterns.utf8char - whitespace
+local digit = lpegpatterns.digit
+----- endofstring = #whitespace + P(-1)
+local endofstring = #whitespace
+
+local word = (digit/"")^0 * (digit/"" * endofstring + digit/" " + nospace)^1
+local anyword = (1-whitespace)^1
+local analyze = Ct((whitespace + Cs(word))^1)
+
+local function unique(tag,requested,loaded)
+ local nofloaded = #loaded
+ if nofloaded == 0 then
+ return ""
+ elseif nofloaded == 1 then
+ return loaded[1]
+ else
+ insert(loaded,1," ") -- no need then for special first word
+ -- insert(loaded, " ")
+ loaded = concat(loaded," ")
+ local t = lpegmatch(analyze,loaded) or { }
+ local h = { }
+ local b = { }
+ for i=1,#t do
+ local ti = t[i]
+ local hi = h[ti]
+ if not hi then
+ h[ti] = 1
+ elseif hi == 1 then
+ h[ti] = 2
+ b[#b+1] = utfsplit(ti," ")
+ end
+ end
+ -- sort
+ local nofbad = #b
+ if nofbad > 0 then
+ local word
+ for i=1,nofbad do
+ local bi = b[i]
+ local p = P(bi[1])
+ for i=2,#bi do
+ p = p * digit * P(bi[i])
+ end
+ if word then
+ word = word + p
+ else
+ word = p
+ end
+ report_initialization("language %a, patterns %a, discarding conflict (0-9)%{[0-9]}t(0-9)",tag,requested,bi)
+ end
+ t, h, b = nil, nil, nil -- permit gc
+ local someword = digit^0 * word * digit^0 * endofstring / ""
+ -- local strip = Cs(someword^-1 * (someword + anyword + whitespace)^1)
+ local strip = Cs((someword + anyword + whitespace)^1)
+ return lpegmatch(strip,loaded) or loaded
+ else
+ return loaded
+ end
+ end
+end
+
+local shared = false
+
+local function loaddefinitions(tag,specification)
+ statistics.starttiming(languages)
+ local data, instance = resolve(tag)
+ local requested = specification.patterns or ""
+ local definitions = settings_to_array(requested)
+ if #definitions > 0 then
+ if trace_patterns then
+ report_initialization("pattern specification for language %a: %s",tag,specification.patterns)
+ end
+ local ploaded = instance:patterns()
+ local eloaded = instance:hyphenation()
+ if not ploaded or ploaded == "" then
+ ploaded = { }
+ else
+ ploaded = { ploaded }
+ end
+ if not eloaded or eloaded == "" then
+ eloaded = { }
+ else
+ eloaded = { eloaded }
+ end
+ local dataused = data.used
+ local ok = false
+ local resources = data.resources or { }
+ data.resources = resources
+ if not shared then
+ local found = resolvers.findfile("lang-exc.lua")
+ if found then
+ shared = dofile(found)
+ if type(shared) == "table" then
+ shared = concat(shared," ")
+ else
+ shared = true
+ end
+ else
+ shared = true
+ end
+ end
+ for i=1,#definitions do
+ local definition = definitions[i]
+ if definition == "" then
+ -- error
+ elseif definition == v_reset then
+ if trace_patterns then
+ report_initialization("clearing patterns for language %a",tag)
+ end
+ instance:clear_patterns()
+ instance:clear_hyphenation()
+ ploaded = { }
+ eloaded = { }
+ elseif not dataused[definition] then
+ dataused[definition] = definition
+ local filename = "lang-" .. definition .. ".lua"
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname == "" then
+ fullname = resolvers.findfile(filename .. ".gz") or ""
+ end
+ if fullname ~= "" then
+ if trace_patterns then
+ report_initialization("loading definition %a for language %a from %a",definition,tag,fullname)
+ end
+ local suffix, gzipped = gzip.suffix(fullname)
+ local loaded = table.load(fullname,gzipped and gzip.load)
+ if loaded then -- todo: version test
+ ok, nofloaded = true, nofloaded + 1
+ sethjcodes(instance,loaded,"patterns",specification.factor)
+ sethjcodes(instance,loaded,"exceptions",specification.factor)
+ local p = validdata(loaded,"patterns",tag)
+ local e = validdata(loaded,"exceptions",tag)
+ if p and p ~= "" then
+ ploaded[#ploaded+1] = p
+ end
+ if e and e ~= "" then
+ eloaded[#eloaded+1] = e
+ end
+ resources[#resources+1] = loaded -- so we can use them otherwise
+ else
+ report_initialization("invalid definition %a for language %a in %a",definition,tag,filename)
+ end
+ elseif trace_patterns then
+ report_initialization("invalid definition %a for language %a in %a",definition,tag,filename)
+ end
+ elseif trace_patterns then
+ report_initialization("definition %a for language %a already loaded",definition,tag)
+ end
+ end
+ if #ploaded > 0 then
+ -- why not always clear
+ instance:clear_patterns()
+ instance:patterns(unique(tag,requested,ploaded))
+ end
+ if #eloaded > 0 then
+ -- why not always clear
+ instance:clear_hyphenation()
+ instance:hyphenation(concat(eloaded," "))
+ end
+ if type(shared) == "string" then
+ instance:hyphenation(shared)
+ end
+ return ok
+ elseif trace_patterns then
+ report_initialization("no definitions for language %a",tag)
+ end
+ statistics.stoptiming(languages)
+end
+
+storage.shared.noflanguages = storage.shared.noflanguages or 0
+
+local noflanguages = storage.shared.noflanguages
+
+function languages.define(tag,parent)
+ noflanguages = noflanguages + 1
+ if trace_patterns then
+ report_initialization("assigning number %a to %a",noflanguages,tag)
+ end
+ numbers[noflanguages] = tag
+ registered[tag] = {
+ tag = tag,
+ parent = parent or "",
+ patterns = "",
+ loaded = false,
+ used = { },
+ dirty = true,
+ number = noflanguages,
+ instance = nil, -- luatex data structure
+ synonyms = { },
+ }
+ storage.shared.noflanguages = noflanguages
+end
+
+function languages.setsynonym(synonym,tag) -- convenience function
+ local l = registered[tag]
+ if l then
+ l.synonyms[synonym] = true -- maybe some day more info
+ end
+end
+
+function languages.installed(separator)
+ return concat(sortedkeys(registered),separator or ",")
+end
+
+function languages.current(n)
+ return numbers[n and tonumber(n) or currentlanguage()]
+end
+
+function languages.associate(tag,script,language) -- not yet used
+ associated[tag] = { script, language }
+end
+
+function languages.association(tag) -- not yet used
+ if not tag then
+ tag = numbers[currentlanguage()]
+ elseif type(tag) == "number" then
+ tag = numbers[tag]
+ end
+ local lat = tag and associated[tag]
+ if lat then
+ return lat[1], lat[2]
+ end
+end
+
+function languages.loadable(tag,defaultlanguage) -- hack
+ local l = registered[tag] -- no synonyms
+ if l and resolvers.findfile("lang-"..l.patterns..".lua") then
+ return true
+ else
+ return false
+ end
+end
+
+-- a bit messy, we will do all language setting in lua as we can now assign
+-- and 'patterns' will go away here.
+
+function languages.unload(tag)
+ local l = registered[tag]
+ if l then
+ l.dirty = true
+ end
+end
+
+if environment.initex then
+
+ function languages.getnumber()
+ return 0
+ end
+
+else
+
+ function languages.getnumber(tag,default,patterns,factor)
+ local l = registered[tag]
+ if l then
+ if l.dirty then
+ l.factor = factor == v_yes and true or false
+ if trace_patterns then
+ report_initialization("checking patterns for %a with default %a",tag,default)
+ end
+ -- patterns is already resolved to parent patterns if applicable
+ if patterns and patterns ~= "" then
+ if l.patterns ~= patterns then
+ l.patterns = patterns
+ if trace_patterns then
+ report_initialization("loading patterns for %a using specification %a",tag,patterns)
+ end
+ loaddefinitions(tag,l)
+ else
+ -- unchanged
+ end
+ elseif l.patterns == "" then
+ l.patterns = tag
+ if trace_patterns then
+ report_initialization("loading patterns for %a using tag",tag)
+ end
+ local ok = loaddefinitions(tag,l)
+ if not ok and tag ~= default then
+ l.patterns = default
+ if trace_patterns then
+ report_initialization("loading patterns for %a using default",tag)
+ end
+ loaddefinitions(tag,l)
+ end
+ end
+ l.loaded = true
+ l.dirty = false
+ end
+ return l.number
+ else
+ return 0
+ end
+ end
+
+ numbers[0] = "null"
+
+ registered.null = {
+ number = 0,
+ instance = new_language(0),
+ }
+
+end
+
+-- not that usefull, global values
+
+function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) end
+function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end
+function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end
+function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end
+-------- languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end
+-------- languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end
+
+-- e['implementer']= 'imple{m}{-}{-}menter'
+-- e['manual'] = 'man{}{}{}'
+-- e['as'] = 'a-s'
+-- e['user-friendly'] = 'user=friend-ly'
+-- e['exceptionally-friendly'] = 'excep-tionally=friend-ly'
+
+local invalid = { "{", "}", "-" }
+
+local function collecthjcodes(data,str)
+ local found = data.extras and data.extras.characters or { }
+ for s in utfcharacters(str) do
+ if not found[s] then
+ found[s] = true
+ end
+ end
+ for i=1,#invalid do -- less checks this way
+ local c = invalid[i]
+ if found[c] then
+ found[c] = nil
+ end
+ end
+ data.extras = { characters = found }
+ sethjcodes(data.instance,data,"extras",data.factor)
+end
+
+function languages.loadwords(tag,filename)
+ local data, instance = resolve(tag)
+ if data then
+ statistics.starttiming(languages)
+ local str = io.loaddata(filename) or ""
+ collecthjcodes(data,str)
+ instance:hyphenation(str)
+ statistics.stoptiming(languages)
+ end
+end
+
+
+function languages.setexceptions(tag,str)
+ local data, instance = resolve(tag)
+ if data then
+ str = strip(str) -- we need to strip leading spaces
+ collecthjcodes(data,str)
+ instance:hyphenation(str)
+ end
+end
+
+function languages.hyphenate(tag,str)
+ -- todo: does this still work?
+ local data, instance = resolve(tag)
+ if data then
+ return instance:hyphenate(str)
+ else
+ return str
+ end
+end
+
+-- hyphenation.define ("zerolanguage")
+-- hyphenation.loadpatterns ("zerolanguage") -- else bug
+-- hyphenation.loadexceptions("zerolanguage") -- else bug
+
+languages.logger = languages.logger or { }
+
+function languages.logger.report()
+ local result, r = { }, 0
+ for tag, l in sortedpairs(registered) do
+ if l.loaded then
+ r = r + 1
+ result[r] = format("%s:%s:%s",tag,l.parent,l.number)
+ end
+ end
+ return r > 0 and concat(result," ") or "none"
+end
+
+-- must happen at the tex end .. will use lang-def.lua
+
+languages.associate('en','latn','eng')
+languages.associate('uk','latn','eng')
+languages.associate('nl','latn','nld')
+languages.associate('de','latn','deu')
+languages.associate('fr','latn','fra')
+
+statistics.register("loaded patterns", function()
+ local result = languages.logger.report()
+ if result ~= "none" then
+ -- return result
+ return format("%s, load time: %s",result,statistics.elapsedtime(languages))
+ end
+end)
+
+-- statistics.register("language load time", function()
+-- -- often zero so we can merge that in the above
+-- return statistics.elapsedseconds(languages, format(", nofpatterns: %s",nofloaded))
+-- end)
+
+-- interface
+
+implement {
+ name = "languagenumber",
+ actions = { languages.getnumber, context },
+ arguments = "4 strings"
+}
+
+implement {
+ name = "installedlanguages",
+ actions = { languages.installed, context },
+}
+
+implement {
+ name = "definelanguage",
+ actions = languages.define,
+ arguments = "2 strings"
+}
+
+implement {
+ name = "setlanguagesynonym",
+ actions = languages.setsynonym,
+ arguments = "2 strings"
+}
+
+implement {
+ name = "unloadlanguage",
+ actions = languages.unload,
+ arguments = "string"
+}
+
+implement {
+ name = "setlanguageexceptions",
+ actions = languages.setexceptions,
+ arguments = "2 strings"
+}
+
+implement {
+ name = "currentprehyphenchar",
+ actions = function()
+ local c = prehyphenchar(tolang())
+ if c and c > 0 then
+ context.char(c)
+ end
+ end
+}
+
+implement {
+ name = "currentposthyphenchar",
+ actions = function()
+ local c = posthyphenchar(tolang())
+ if c and c > 0 then
+ context.char(c)
+ end
+ end
+}
diff --git a/tex/context/base/mkiv/lang-ini.lua b/tex/context/base/mkiv/lang-ini.lua
index ac5b2c113..7a8aab818 100644
--- a/tex/context/base/mkiv/lang-ini.lua
+++ b/tex/context/base/mkiv/lang-ini.lua
@@ -48,7 +48,6 @@ local sethjcode = lang.sethjcode
local uccodes = characters.uccodes
local lccodes = characters.lccodes
-lang.exceptions = lang.hyphenation
local new_language = lang.new
languages = languages or {}
diff --git a/tex/context/base/mkiv/lang-ini.mkxl b/tex/context/base/mkiv/lang-ini.mkxl
index f5831a5ea..6d0649fa8 100644
--- a/tex/context/base/mkiv/lang-ini.mkxl
+++ b/tex/context/base/mkiv/lang-ini.mkxl
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module needs a further cleanup (real split between ii/iv).
+% We can protect \currentlanguage etc too.
% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]}
@@ -22,7 +22,7 @@
\writestatus{loading}{ConTeXt Language Macros / Initialization}
-\registerctxluafile{lang-ini}{}
+\registerctxluafile{lang-ini}{autosuffix}
\registerctxluafile{lang-def}{}
\registerctxluafile{lang-cnt}{}
@@ -74,14 +74,14 @@
\def\currentusedlanguage{\currentlanguage}
-\def\defaultlanguage#1%
+\permanent\def\defaultlanguage#1%
{\ifcsname\??language#1\s!default\endcsname
\expandafter\defaultlanguage\lastnamedcs
\else
#1%
\fi}
-\def\languageparameter#1%
+\permanent\def\languageparameter#1%
{\ifcsname\??language\currentlanguage#1\endcsname
\lastnamedcs
\orelse\ifcsname\??language\currentlanguage\s!default\endcsname
@@ -90,7 +90,7 @@
\lastnamedcs
\fi}
-\def\specificlanguageparameter#1#2%
+\permanent\def\specificlanguageparameter#1#2%
{\ifcsname\??language#1#2\endcsname
\lastnamedcs
\orelse\ifcsname\??language#1\s!default\endcsname
@@ -99,7 +99,7 @@
\lastnamedcs
\fi}
-\def\mainlanguageparameter#1%
+\permanent\def\mainlanguageparameter#1%
{\ifcsname\??language\currentmainlanguage#1\endcsname
\lastnamedcs
\orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname
@@ -108,9 +108,9 @@
\lastnamedcs
\fi}
-\let\usedlanguageparameter\languageparameter
+\aliased\let\usedlanguageparameter\languageparameter
-\def\askedlanguageparameter#1% assumes \currentusedlanguage being set
+\permanent\def\askedlanguageparameter#1% assumes \currentusedlanguage being set
{\ifcsname\??language\currentusedlanguage#1\endcsname
\lastnamedcs
\orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname
@@ -119,25 +119,25 @@
\lastnamedcs
\fi}
-\unexpanded\def\setusedlanguage#1%
+\permanent\protected\def\setusedlanguage#1%
{\edef\currentusedlanguage{\reallanguagetag{#1}}%
\ifempty\currentusedlanguage
\let\currentusedlanguage \currentlanguage
- \let\usedlanguageparameter\languageparameter
+ \enforced\let\usedlanguageparameter\languageparameter
\orelse\ifx\currentusedlanguage\v!global
\let\currentusedlanguage \currentmainlanguage
- \let\usedlanguageparameter\mainlanguageparameter
+ \enforced\let\usedlanguageparameter\mainlanguageparameter
\orelse\ifx\currentusedlanguage\v!local
\let\currentusedlanguage \currentlanguage
- \let\usedlanguageparameter\languageparameter
+ \enforced\let\usedlanguageparameter\languageparameter
\else
- \let\usedlanguageparameter\askedlanguageparameter
+ \enforced\let\usedlanguageparameter\askedlanguageparameter
\fi}
-\unexpanded\def\setupcurrentlanguage[#1]%
+\permanent\protected\def\setupcurrentlanguage[#1]%
{\setcurrentlanguage\currentmainlanguage{#1}}
-\unexpanded\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
+\permanent\protected\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
{\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage
\ifempty\xaskedlanguage \else
\ifempty\currentmainlanguage\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
@@ -176,9 +176,9 @@
\newtoks \everysetuplanguage
-\def\installedlanguages{\clf_installedlanguages}
+\aliased\let\installedlanguages\clf_installedlanguages % no need for \clf_
-\unexpanded\def\doifelselanguage#1%
+\permanent\protected\def\doifelselanguage#1%
{\ifcsname\??language#1\c!state\endcsname
\expandafter\firstoftwoarguments
\else
@@ -187,15 +187,12 @@
\let\doiflanguageelse\doifelselanguage
-\def\reallanguagetag#1%
+\permanent\def\reallanguagetag#1%
{\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi}
% \language[#1] gave unwanted side effect of loading language specifics
-\unexpanded\def\installlanguage
- {\dodoubleargument\lang_basics_install}
-
-\def\lang_basics_install[#1][#2]%
+\permanent\tolerant\protected\def\installlanguage[#1]#*[#2]%
{\ifcondition\validassignment{#2}%
\doifelselanguage{#1}
{\getparameters[\??language#1][#2]}
@@ -218,7 +215,7 @@
%D feature is present because we used dutch mnemonics in the dutch version, but
%D nowadays conform a standard.
-\unexpanded\def\doifelsepatterns#1%
+\permanent\protected\def\doifelsepatterns#1%
{\begingroup % will change
\lang_basics_set_current[#1]%
\ifnum\normallanguage>\zerocount
@@ -227,7 +224,7 @@
\endgroup\expandafter\secondoftwoarguments
\fi}
-\let\doifpatternselse\doifelsepatterns
+\aliased\let\doifpatternselse\doifelsepatterns
%D \macros
%D {setuplanguage}
@@ -238,27 +235,26 @@
%D
%D Beware, this command can only be used when a language is installed.
-\unexpanded\def\setuplanguage
- {\dodoubleempty\lang_basics_setup}
-
\ifdefined\lang_basics_synchronize \else
\let\lang_basics_synchronize\relax % be nice for setups till we have one
\fi
\installmacrostack\currentlanguage
-\def\lang_basics_setup[#1][#2]%
- {\ifsecondargument
+\permanent\tolerant\protected\def\setuplanguage[#1]#*[#2]%
+ {\ifarguments
+ % only synchronize
+ \or
+ \let\currentsetuplanguage\currentlanguage
+ \getparameters[\??language\currentsetuplanguage][#1]%
+ \the\everysetuplanguage
+ \or
\push_macro_currentlanguage % can be default
\edef\currentsetuplanguage{\reallanguagetag{#1}}%
\getparameters[\??language\currentsetuplanguage][#2]%
\the\everysetuplanguage
\pop_macro_currentlanguage
%\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default)
- \else
- \let\currentsetuplanguage\currentlanguage
- \getparameters[\??language\currentsetuplanguage][#1]%
- \the\everysetuplanguage
\fi
\lang_basics_synchronize}
@@ -316,8 +312,8 @@
%D
%D Just to make things easy we can ask for the current date specification by saying:
-\def\currentdatespecification{\languageparameter\c!date}
-\def\currenttimespecification{\languageparameter\c!time}
+\permanent\def\currentdatespecification{\languageparameter\c!date}
+\permanent\def\currenttimespecification{\languageparameter\c!time}
%D Carefull reading of these macros shows that it's legal to say
%D
@@ -398,9 +394,9 @@
% This is the old implementation: a hack that sets the min values, because we want
% to keep the language set:
%
-% \unexpanded\def\nohyphens % nicer for url's
+% \protected\def\nohyphens % nicer for url's
% {\ifx\dohyphens\relax
-% \unexpanded\edef\dohyphens
+% \protected\edef\dohyphens
% {\hyphenminoffset\the\hyphenminoffset\relax
% \lang_basics_synchronize_min_max}%
% \fi
@@ -433,10 +429,10 @@
+ \permitmathreplacehyphenationmodecode % and again we're more permissive
\relax
-\unexpanded\def\dohyphens{\hyphenationmode\completehyphenationmodecode}
-\unexpanded\def\nohyphens{\hyphenationmode\zerocount}
+\permanent\protected\def\dohyphens{\hyphenationmode\completehyphenationmodecode}
+\permanent\protected\def\nohyphens{\hyphenationmode\zerocount}
-\unexpanded\def\usehyphensparameter#1%
+\permanent\protected\def\usehyphensparameter#1%
{\edef\p_hyphens{#1\c!hyphens}%
\ifx\p_hyhens\v!no
\nohyphens
@@ -446,17 +442,17 @@
%D The rest stays the same as in mkiv:
-\unexpanded\def\lesshyphens
+\permanent\protected\def\lesshyphens
{\advance\hyphenminoffset\plusone
\lang_basics_synchronize_min_max}
-\unexpanded\def\morehyphens
+\permanent\protected\def\morehyphens
{\ifcase\hyphenminoffset \else
\advance\hyphenminoffset\minusone
\fi
\lang_basics_synchronize_min_max}
-\unexpanded\def\lang_basics_synchronize_min_max % maybe store this at the lua end
+\protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end
{% these values are stored along with glyph nodes
\lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
\righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax
@@ -469,7 +465,7 @@
\lang_basics_synchronize_min_max
\to \everylanguage
-\unexpanded\def\unhyphenated
+\permanent\protected\def\unhyphenated
{\groupedcommand{\lefthyphenmin\maxdimen}\donothing}
% \appendtoks
@@ -509,7 +505,7 @@
% new experimental feature
-\unexpanded\def\setuplanguages
+\permanent\protected\def\setuplanguages
{\setuplanguage[\s!default]}
% \setuplanguages[\c!font=\v!auto]
@@ -537,36 +533,40 @@
\fi
\fi}
-\unexpanded\def\uselanguageparameter#1%
+\protected\def\uselanguageparameter#1%
{\edef\askedlanguage{#1\c!language}%
\ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
-\unexpanded\def\douselanguageparameter#1% fast setter
+\protected\def\douselanguageparameter#1% fast setter
{\edef\askedlanguage{#1}%
\ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
-\unexpanded\def\lang_basics_set_current[#1]%
+\protected\def\lang_basics_set_current[#1]%
{\edef\askedlanguage{#1}%
\ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
-\unexpanded\def\language
- {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
+\pushoverloadmode
-\let\setlanguage\language % we make these synonyms
+ \permanent\protected\def\language
+ {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
-\let\patterns\gobbleoneargument
+ \let\setlanguage\language % we make these synonyms
+
+ \let\patterns\gobbleoneargument
+
+\popoverloadmode
\newcount\mainlanguagenumber
%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par}
%D inside the group!
-\unexpanded\def\startlanguage
+\permanent\protected\def\startlanguage
{\begingroup\language}
-\let\stoplanguage\endgroup
+\permanent\let\stoplanguage\endgroup
-\unexpanded\def\mainlanguage[#1]%
+\permanent\protected\def\mainlanguage[#1]%
{\edef\askedlanguage{#1}%
\ifempty\askedlanguage
\orelse\ifcsname\??languagelinked\askedlanguage\endcsname
@@ -590,10 +590,10 @@
%D Used at all?
-\def\splitsequence#1#2%
+\permanent\def\splitsequence#1#2%
{\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}}
-\def\splitsymbol#1%
+\permanent\def\splitsymbol#1%
{\splitsequence{#1}{\languageparameter\c!limittext}}
%D Just like with subsentence boundary symbols, quotes placement depends on the
@@ -704,25 +704,22 @@
%D \stoptable
%D \protect
-\unexpanded\def\nopatterns{\normallanguage\minusone}
+\permanent\protected\def\nopatterns{\normallanguage\minusone}
%D We default to the language belonging to the interface. This is one of the few
%D places outside the interface modules where \type {\startinterface} is used.
\setupcurrentlanguage[\s!en]
-\unexpanded\def\initializemainlanguage
+\permanent\protected\def\initializemainlanguage
{\mainlanguage[\currentlanguage]%
\showmessage\m!languages9\currentlanguage}
%D New:
-\let\stopexceptions\relax
+\permanent\let\stopexceptions\relax
-\unexpanded\def\startexceptions
- {\dosingleempty\lang_basics_start_exceptions}
-
-\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not?
+\tolerant\permanent\protected\def\startexceptions[#1]#:#2\stopexceptions
{\begingroup
\edef\askedlanguage{\reallanguagetag{#1}}%
\ifempty\askedlanguage
@@ -731,26 +728,38 @@
\clf_setlanguageexceptions{\askedlanguage}{#2}%
\endgroup}
-\unexpanded\def\hyphenation
+\pushoverloadmode
+
+\permanent\protected\def\hyphenation
{\clf_setlanguageexceptions{\currentlanguage}}
+\popoverloadmode
+
%D New:
-\unexpanded\def\traceddiscretionary#1#%
+\permanent\protected\def\traceddiscretionary#1#%
{\dontleavehmode\lang_basics_traced_discretionary{#1}}
-\unexpanded\def\lang_basics_traced_discretionary#1#2#3#4%
+\protected\def\lang_basics_traced_discretionary#1#2#3#4%
{\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}}
\installtextracker
{discretionaries}
- {\let\discretionary\traceddiscretionary}
- {\let\discretionary\normaldiscretionary}
+ {\enforced\let\discretionary\traceddiscretionary}
+ {\enforced\let\discretionary\normaldiscretionary}
-\unexpanded\def\samplediscretionary
+\permanent\protected\def\samplediscretionary
{\traceddiscretionary
{pre\clf_currentprehyphenchar}%
{\clf_currentposthyphenchar post}%
{replace}}
+%D Also new:
+
+\immutable\chardef\nokerningcode \numexpr\noleftkerncode +\norightkerncode \relax
+\immutable\chardef\noligaturingcode\numexpr\noleftligaturecode+\norightligaturecode\relax
+
+\permanent\protected\def\nokerning {\bitwiseflip\glyphoptions\nokerningcode}
+\permanent\protected\def\noligaturing{\bitwiseflip\glyphoptions\noligaturingcode}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/lang-lab.mkxl b/tex/context/base/mkiv/lang-lab.mkxl
index bf503c069..d627e5a42 100644
--- a/tex/context/base/mkiv/lang-lab.mkxl
+++ b/tex/context/base/mkiv/lang-lab.mkxl
@@ -21,7 +21,7 @@
%D Left-overs:
\ifdefined\sixperemspace \else
- \def\sixperemspace{\normalUchar"2006}
+ \permanent\def\sixperemspace{\normalUchar"2006}
\fi
%D In this module we deal with language dependant labels and prefixes, like in {\em
@@ -62,14 +62,11 @@
\let\currentlabelcategory\empty
-\unexpanded\def\definelabelclass
- {\dodoubleempty\lang_labels_define_class}
-
-\def\lang_labels_define_class[#1][#2]%
+\permanent\tolerant\protected\def\definelabelclass[#1]#*[#2]%
{\normalexpanded
{\lang_labels_define_class_indeed
{#1}%
- {\ifsecondargument#2\else\zerocount\fi}%
+ {\ifchknum#2\or#2\else\zerocount\fi}%
\expandafter\noexpand\csname dogetupsome#1text\endcsname
\expandafter\noexpand\csname #1language\endcsname
\expandafter\noexpand\csname dodogetupsome#1text\endcsname
@@ -82,11 +79,11 @@
\let\thetextprefix\empty
-\unexpanded\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9%
- {\setuvalue{setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
- \setuvalue{preset#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}%
- \setuvalue{copy#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_copy}%
- \setuvalue{start#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dotripleempty\lang_labels_text_prefix_start[#1]}%
+\protected\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9%
+ {\setuvalue {setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}%
+ \setuvalue{preset#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}%
+ \setuvalue {copy#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_copy }%
+ \setuvalue {start#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_start[#1]}%
\letvalue{stop#1text}\relax
\def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}%
\ifnum#2=\plustwo % used for math and tags
@@ -117,27 +114,27 @@
\let#8\gobbletwoarguments
\let#9#3%
\else
- \unexpanded\def#3{#5#4}%
- \unexpanded\def#5##1##2%
+ \protected\def#3{#5#4}%
+ \protected\def#5##1##2%
{\ifcsname\??label#1:##1:##2\endcsname
%\expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs
\orelse\ifcsname\??language#4\s!default\endcsname
%\expandafter#5\csname\??language#4\s!default\endcsname{##2}%
\expandafter#5\lastnamedcs{##2}%
\orelse\ifcsname\??label#1:##2\endcsname
%\expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs
\orelse\ifcsname\??label#1:\s!en:##2\endcsname
%\expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\lastnamedcs
+ \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs
\else
- \let\thetextprefix\dummytextprefix
+ \enforced\let\thetextprefix\dummytextprefix
\fi}%
- \unexpanded\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
- \unexpanded\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}%
- \unexpanded\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2
- \unexpanded\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \protected\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
+ \protected\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}%
+ \protected\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2
+ \protected\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}%
\fi
\appendtoks
\let#6\firstofoneargument % to be checked
@@ -146,10 +143,14 @@
\let#9\firstofoneargument % to be checked
\to \everysimplifycommands}
+% why not lang_* ?
+
\let\flushleftlabelclass \firstoftwoarguments
\let\flushrightlabelclass\secondoftwoarguments
-\def\flushbothlabelclass #1#2#3{#1#3#2}
-\def\dummytextprefix {\empty\empty}
+
+\permanent\def\flushbothlabelclass#1#2#3{#1#3#2}
+
+\permanent\def\dummytextprefix{\empty\empty}
%D \macros
%D {headtext, labeltext, leftlabeltext, rightlabeltext, labeltexts}
@@ -172,13 +173,13 @@
\let\currenttextprefixtag \s!unknown
\let\currenttextprefixclass\s!unknown
-\def\lang_labels_text_prefix_start[#1][#2][#3]% class language name
- {\ifthirdargument
- \edef\currenttextprefixtag{\reallanguagetag{#2}}%
- \edef\currenttextprefixname{#3}%
- \else
+\tolerant\def\lang_labels_text_prefix_start[#1]#*[#2]#*[#3]% class language name
+ {\ifarguments\or\or
\edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
\edef\currenttextprefixname{#2}%
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag{#2}}%
+ \edef\currenttextprefixname{#3}%
\fi
\grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed}
@@ -186,13 +187,13 @@
{\expandafter\edef\csname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname%
{{\clf_strip{#1}}\empty}}
-\def\lang_labels_text_prefix_setup[#1][#2]%
- {\ifsecondargument
- \edef\currenttextprefixtag{\reallanguagetag{#1}}%
- \processcommalist[#2]\lang_labels_text_prefix_setup_indeed
- \else
+\tolerant\def\lang_labels_text_prefix_setup[#1]#*[#2]%
+ {\ifarguments\or
\edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
\processcommalist[#1]\lang_labels_text_prefix_setup_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_setup_indeed
\fi}
\def\lang_labels_text_prefix_setup_indeed#1%
@@ -240,17 +241,17 @@
\def\lang_labels_text_prefix_assign_dumb#1[#2,#3]%
{\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
-\unexpanded\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end
+\permanent\protected\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end
{%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}%
\expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right
-\def\lang_labels_text_prefix_copy[#1][#2]%
- {\ifsecondargument
- \edef\currenttextprefixtag{\reallanguagetag{#1}}%
- \processcommalist[#2]\lang_labels_text_prefix_copy_indeed
- \else
+\tolerant\def\lang_labels_text_prefix_copy[#1]#*[#2]%
+ {\ifarguments\or
\edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
\processcommalist[#1]\lang_labels_text_prefix_copy_indeed
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\lang_labels_text_prefix_copy_indeed
\fi}
\def\lang_labels_text_prefix_copy_indeed#1%
@@ -298,10 +299,7 @@
\installcorenamespace{translation}
-\unexpanded\def\translate
- {\dosingleempty\lang_translate}
-
-\def\lang_translate[#1]%
+\permanent\tolerant\protected\def\translate[#1]%
{\getparameters[\??translation][#1]%
\ifcsname\??translation\currentlanguage\endcsname
\lastnamedcs
@@ -328,7 +326,9 @@
%D \assigntranslation[en=something,nl=iets]\to\command
%D \stoptyping
-\unexpanded\def\assigntranslation[#1]\to#2% bad, this \to
+% nicer is \edef\command{\translated[...]} ... todo
+
+\permanent\protected\def\assigntranslation[#1]\to#2% bad, this \to
{\getparameters[\??translation][#1]%
\edef#2{\begincsname\??translation\currentlanguage\endcsname}}
@@ -352,10 +352,7 @@
%D \getbuffer
%D \stoplines
-\unexpanded\def\commalistsentence
- {\dodoubleempty\typo_helpers_concat_comma_list}
-
-\def\typo_helpers_concat_comma_list[#1][#2]%
+\permanent\tolerant\protected\def\commalistsentence[#1]#*[#2]%
{\clf_concatcommalist
text {#1}%
separators {#2}%
@@ -370,6 +367,6 @@
%D Goodie (handy at \LUA\ end):
-\unexpanded\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases!
+\permanent\protected\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases!
\protect \endinput
diff --git a/tex/context/base/mkiv/lang-mis.mkiv b/tex/context/base/mkiv/lang-mis.mkiv
index 3ec29a782..4d81c01fa 100644
--- a/tex/context/base/mkiv/lang-mis.mkiv
+++ b/tex/context/base/mkiv/lang-mis.mkiv
@@ -254,12 +254,12 @@
\def\lang_discretionaries_check_after
{\setfalse\punctafterdiscretionary
\setfalse\spaceafterdiscretionary
- \ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \else
- \ifx\space \nextnext \settrue \spaceafterdiscretionary \else
- \ifx .\nextnext \settrue \punctafterdiscretionary \else
- \ifx ,\nextnext \settrue \punctafterdiscretionary \else
- \ifx :\nextnext \settrue \punctafterdiscretionary \else
- \ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
+ \ifx\blankspace\nexttoken \settrue \spaceafterdiscretionary \else
+ \ifx\space \nexttoken \settrue \spaceafterdiscretionary \else
+ \ifx .\nexttoken \settrue \punctafterdiscretionary \else
+ \ifx ,\nexttoken \settrue \punctafterdiscretionary \else
+ \ifx :\nexttoken \settrue \punctafterdiscretionary \else
+ \ifx ;\nexttoken \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
\letvalue{\??discretionarymode m}\handlemathmodediscretionary
@@ -268,7 +268,7 @@
\let\nextnextnext\egroup
\def\next##1#1%
{\def\next{\activedododotextmodediscretionary#1{##1}}%
- \futurelet\nextnext\next}%
+ \futurelet\nexttoken\next}%
\next}
\let\discretionarytoken \relax
@@ -279,7 +279,7 @@
\def\textmodediscretionary{\handletextmodediscretionary{#1}}%
\lang_discretionaries_check_after
\ifx\discretionarytoken\empty
- \ifx#1\nextnext % takes care of ||| and +++ and ......
+ \ifx#1\nexttoken % takes care of ||| and +++ and ......
\ifcsname\??discretionaryaction\string#1\endcsname
\lastnamedcs
\else\ifconditional\spaceafterdiscretionary
@@ -296,7 +296,7 @@
\else
\lang_discretionaries_check_before
% the next line has been changed (20050203)
- % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak
+ % \prewordbreak\hbox{\textmodediscretionary\nexttoken}\postwordbreak
% but an hbox blocks a possible \discretionary
\ifcsname\??discretionaryaction\endcsname
\lastnamedcs
diff --git a/tex/context/base/mkiv/lang-mis.mkxl b/tex/context/base/mkiv/lang-mis.mkxl
index 5ed131d25..9515a1f8e 100644
--- a/tex/context/base/mkiv/lang-mis.mkxl
+++ b/tex/context/base/mkiv/lang-mis.mkxl
@@ -150,8 +150,8 @@
% hm why ex
-\ifx\compoundhyphen \undefined
- \unexpanded\def\compoundhyphen {\hbox{-\kern-.10775\emwidth-}} % .25\exheight
+\ifx\compoundhyphen\undefined
+ \permanent\protected\def\compoundhyphen{\hbox{-\kern-.10775\emwidth-}} % .25\exheight
\fi
%D The last two variables are needed for subsentences |<|like this one|>| which we
@@ -159,12 +159,12 @@
%D compound characters like |-| or || to be separated from the words. \TEX\ hackers
%D will recognise the next two macro's:
-\ifx\prewordbreak \undefined \unexpanded\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
-\ifx\postwordbreak\undefined \unexpanded\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi
-\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % language specific
+\ifx\prewordbreak \undefined \permanent\protected\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
+\ifx\postwordbreak\undefined \permanent\protected\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi
+\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % will be overloaded
-%unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces
-\unexpanded\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces
+%frozen\protected\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces
+\permanent\protected\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces
%D \macros
%D {beginofsubsentence,endofsubsentence,
@@ -191,22 +191,22 @@
\installcorenamespace{discretionaryboth}
\installcorenamespace{discretionarymode}
-\unexpanded\def\installdiscretionary#1#2%
+\permanent\protected\def\installdiscretionary#1#2%
{\setevalue{\??discretionarymath\detokenize{#1}}{\detokenize{#1}}% ?
\setvalue {\??discretionarytext\detokenize{#1}}{#2}%
\setvalue {\??discretionaryboth\detokenize{#1}}{\lang_discretionaries_command#1}%
\scratchcounter\expandafter`\detokenize{#1}%
\expandafter\uedcatcodecommand\expandafter\ctxcatcodes\expandafter\scratchcounter\csname\??discretionaryboth\detokenize{#1}\endcsname}
-\unexpanded\def\handlemathmodediscretionary#1{\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs}
-\unexpanded\def\handletextmodediscretionary#1{\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs}
+\permanent\protected\def\handlemathmodediscretionary#1{\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs}
+\permanent\protected\def\handletextmodediscretionary#1{\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs}
-\unexpanded\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete
+\permanent\protected\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete
\setnewconstant\discretionarymode\plusone
-\unexpanded\def\ignorediscretionaries{\discretionarymode\zerocount}
-\unexpanded\def\obeydiscretionaries {\discretionarymode\plusone}
+\permanent\protected\def\ignorediscretionaries{\discretionarymode\zerocount}
+\permanent\protected\def\obeydiscretionaries {\discretionarymode\plusone}
\def\lang_discretionaries_command
{% if direct if, we need \relax for lookahead in math mode
@@ -252,12 +252,12 @@
\def\lang_discretionaries_check_after
{\setfalse\punctafterdiscretionary
\setfalse\spaceafterdiscretionary
- \ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \orelse
- \ifx\space \nextnext \settrue \spaceafterdiscretionary \orelse
- \ifx .\nextnext \settrue \punctafterdiscretionary \orelse
- \ifx ,\nextnext \settrue \punctafterdiscretionary \orelse
- \ifx :\nextnext \settrue \punctafterdiscretionary \orelse
- \ifx ;\nextnext \settrue \punctafterdiscretionary \fi}
+ \ifx\blankspace\nexttoken \settrue \spaceafterdiscretionary \orelse
+ \ifx\space \nexttoken \settrue \spaceafterdiscretionary \orelse
+ \ifx .\nexttoken \settrue \punctafterdiscretionary \orelse
+ \ifx ,\nexttoken \settrue \punctafterdiscretionary \orelse
+ \ifx :\nexttoken \settrue \punctafterdiscretionary \orelse
+ \ifx ;\nexttoken \settrue \punctafterdiscretionary \fi}
\letvalue{\??discretionarymode m}\handlemathmodediscretionary
@@ -266,18 +266,18 @@
\let\nextnextnext\egroup
\def\next##1#1%
{\def\next{\activedododotextmodediscretionary#1{##1}}%
- \futurelet\nextnext\next}%
+ \futurelet\nexttoken\next}%
\next}
\let\discretionarytoken \relax
\let\textmodediscretionary\relax
-\unexpanded\def\activedododotextmodediscretionary#1#2%
+\permanent\protected\def\activedododotextmodediscretionary#1#2%
{\edef\discretionarytoken{\detokenize{#2}}%
\def\textmodediscretionary{\handletextmodediscretionary{#1}}%
\lang_discretionaries_check_after
\ifx\discretionarytoken\empty
- \ifx#1\nextnext % takes care of ||| and +++ and ......
+ \ifx#1\nexttoken % takes care of ||| and +++ and ......
\ifcsname\??discretionaryaction\string#1\endcsname
\lastnamedcs
\orelse\ifconditional\spaceafterdiscretionary
@@ -294,7 +294,7 @@
\else
\lang_discretionaries_check_before
% the next line has been changed (20050203)
- % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak
+ % \prewordbreak\hbox{\textmodediscretionary\nexttoken}\postwordbreak
% but an hbox blocks a possible \discretionary
\ifcsname\??discretionaryaction\endcsname
\lastnamedcs
@@ -333,7 +333,7 @@
%D In those situations where the nature of characters is less predictable, we can
%D use the more direct approach:
-\unexpanded\def\directdiscretionary
+\permanent\protected\def\directdiscretionary
{\csname\??discretionarymode
\ifcase\discretionarymode
n%
@@ -342,7 +342,7 @@
\fi
\endcsname}
-\unexpanded\def\indirectdiscretionary
+\permanent\protected\def\indirectdiscretionary
{\csname\??discretionarymode
\ifcase\discretionarymode
n%
@@ -365,7 +365,7 @@
{\wordboundary\discretionary{\hbox{#1}}{}{\hbox{#1}}\wordboundary}
%{\discretionary options \plusthree{\hbox{#1}}{}{\hbox{#1}}}
-\unexpanded\def\definetextmodediscretionary #1
+\permanent\protected\def\definetextmodediscretionary #1
{\setvalue{\??discretionaryaction\detokenize{#1}}}
% \start \hsize 1mm
@@ -479,7 +479,7 @@
%D \installdiscretionary | +
%D \installdiscretionary + =
-\def\defaultdiscretionaryhyphen{\compoundhyphen}
+\permanent\protected\def\defaultdiscretionaryhyphen{\compoundhyphen}
\installdiscretionary | \defaultdiscretionaryhyphen % installs in ctx and prt will fall back on it
@@ -494,11 +494,11 @@
%D \goto{Some||Long||Word}
%D \stoptyping
-\unexpanded\def\fakecompoundhyphen
- {\def\|{\mathortext\vert\lang_compounds_fake_hyphen}}
+\permanent\protected\def\fakecompoundhyphen
+ {\enforced\permanent\protected\def\|{\mathortext\vert\lang_compounds_fake_hyphen}}
\def\lang_compounds_fake_hyphen
- {\def##1|%
+ {\enforced\permanent\protected\def##1|%
{\doifelsenothing{##1}\compoundhyphen{##1}%
\kern\compoundbreakpoint\allowbreak}}
@@ -510,7 +510,7 @@
%D but, like the ones implemented earlier, this one also looks ahead for spaces and
%D grouping tokens.
-\unexpanded\def\midworddiscretionary
+\permanent\protected\def\midworddiscretionary
{\futurelet\nexttoken\lang_discretionaries_mid_word}
\def\lang_discretionaries_mid_word
@@ -552,10 +552,10 @@
\catcode\barasciicode\activecatcode
- \unexpanded\gdef\compound#1{|#1|}
+ \permanent\protected\gdef\compound#1{|#1|}
\doglobal \appendtoks
- \def|#1|{\ifx#1\empty\empty-\else#1\fi}%
+ \enforced\permanent\protected\def|#1|{\ifx#1\empty\empty-\else#1\fi}%
\to \everysimplifycommands
\egroup
@@ -575,7 +575,7 @@
%D
%D \typebuffer \blank {\hsize3mm\getbuffer\par} \blank
-\unexpanded\def\compounddiscretionary
+\permanent\protected\def\compounddiscretionary
{\discretionary
options \plusthree
{\ifnum\prehyphenchar >\zerocount\char\prehyphenchar \fi}%
diff --git a/tex/context/base/mkiv/lang-rep.lua b/tex/context/base/mkiv/lang-rep.lua
index a48215781..2a3c8a7fa 100644
--- a/tex/context/base/mkiv/lang-rep.lua
+++ b/tex/context/base/mkiv/lang-rep.lua
@@ -164,50 +164,6 @@ function languages.replacements.addlist(category,list)
end
end
-local function hit(a,head)
- local tree = trees[a]
- if tree then
- local root = tree[getchar(head)]
- if root then
- local current = getnext(head)
- local lastrun = false
- local lastfinal = false
- while current do
- local char, id = isglyph(current)
- if not char and id == glue_code then
- local s = getsubtype(current)
- if s == spaceskip_code or s == xspaceskip_code then
- char = 32 -- if needed we can also deal with spaces and special nbsp and such
- end
- end
- if char then
- local newroot = root[char]
- if not newroot then
- return lastrun, lastfinal
- else
- local final = newroot.final
- if final then
- if trace_details then
- report_replacement("hitting word %a, replacement %a",final.word,final.replacement)
- end
- lastrun = current
- lastfinal = final
- else
- root = newroot
- end
- end
- current = getnext(current)
- else
- break
- end
- end
- if lastrun then
- return lastrun, lastfinal
- end
- end
- end
-end
-
local function tonodes(list,template)
local head, current
for i=1,#list do
@@ -222,120 +178,241 @@ local function tonodes(list,template)
return head
end
+local is_punctuation = characters.is_punctuation
+
+-- We can try to be clever and use the fact that there is no match to skip
+-- over to the next word but it is gives fuzzy code so for now I removed
+-- that optimization (when I really need a high performance version myself
+-- I will look into it (but so far I never used this mechanism myself).
+--
+-- We used to have the hit checker as function but is got messy when checks
+-- for punctuation was added.
+
+local function replace(head,first,last,final,hasspace,overload)
+ local current = first
+ local prefirst = getprev(first) or head
+ local postlast = getnext(last)
+ local oldlength = final.oldlength
+ local newcodes = final.newcodes
+ local newlength = newcodes and #newcodes or 0
+ if trace_replacements then
+ report_replacement("replacing word %a by %a",final.word,final.replacement)
+ end
+ if hasspace or final.special then
+ -- It's easier to delete and insert so we do just that. On the todo list is
+ -- turn injected spaces into glue but easier might be to let the char break
+ -- handler do that ...
+ local prev = getprev(current)
+ local next = getnext(last)
+ local list = current
+ setnext(last)
+ setlink(prev,next)
+ current = prev
+ if not current then
+ head = nil
+ end
+ local i = 1
+ while i <= newlength do
+ local codes = newcodes[i]
+ if type(codes) == "table" then
+ local method = codes[1]
+ if method == "discretionary" then
+ local pre, post, replace = codes[2], codes[3], codes[4]
+ if pre then
+ pre = tonodes(pre,first)
+ end
+ if post then
+ post = tonodes(post,first)
+ end
+ if replace then
+ replace = tonodes(replace,first)
+ end
+ -- todo: also set attr
+ local new = new_disc(pre,post,replace)
+ setattrlist(new,first)
+ head, current = insert_after(head,current,new)
+ elseif method == "noligature" then
+ -- not that efficient to copy but ok for testing
+ local list = codes[2]
+ if list then
+ for i=1,#list do
+ local new = copy_node(first)
+ setchar(new,list[i])
+ setattr(new,a_noligature,1)
+ head, current = insert_after(head,current,new)
+ end
+ else
+ local new = copy_node(first)
+ setchar(new,zwnj)
+ head, current = insert_after(head,current,new)
+ end
+ else
+ report_replacement("unknown method %a",method or "?")
+ end
+ else
+ local new = copy_node(first)
+ setchar(new,codes)
+ head, current = insert_after(head,current,new)
+ end
+ i = i + 1
+ end
+ flush_list(list)
+ elseif newlength == 0 then
+ -- we overload
+ elseif oldlength == newlength then
+ if final.word ~= final.replacement then
+ for i=1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ end
+ current = getnext(final)
+ elseif oldlength < newlength then
+ for i=1,newlength-oldlength do
+ local n = copy_node(current)
+ setchar(n,newcodes[i])
+ head, current = insert_node_before(head,current,n)
+ current = getnext(current)
+ end
+ for i=newlength-oldlength+1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ else
+ for i=1,oldlength-newlength do
+ head, current = remove_node(head,current,true)
+ end
+ for i=1,newlength do
+ setchar(current,newcodes[i])
+ current = getnext(current)
+ end
+ end
+ if overload then
+ overload(final,getnext(prefirst),getprev(postlast))
+ end
+ return head, postlast
+end
+
+-- we handle just one space
+
function replacements.handler(head)
- local current = head
- local overload = attributes.applyoverloads
+ local current = head
+ local overload = attributes.applyoverloads
+ local mode = false -- we're in word or punctuation mode
+ local wordstart = false
+ local wordend = false
+ local prevend = false
+ local prevfinal = false
+ local tree = false
+ local root = false
+ local hasspace = false
while current do
- if getid(current) == glyph_code then
+ local id = getid(current) -- or use the char getter
+ if id == glyph_code then
local a = getattr(current,a_replacements)
if a then
- local last, final = hit(a,current)
- if last then
- local precurrent = getprev(current) or head
- local oldlength = final.oldlength
- local newcodes = final.newcodes
- local newlength = newcodes and #newcodes or 0
- if trace_replacement then
- report_replacement("replacing word %a by %a",final.word,final.replacement)
- end
- if final.special then
- -- easier is to delete and insert (a simple callout to tex would be more efficient)
- -- maybe just walk over a replacement string instead
- local prev = getprev(current)
- local next = getnext(last)
- local list = current
- setnext(last)
- setlink(prev,next)
- current = prev
- if not current then
- head = nil
- end
- local i = 1
- while i <= newlength do
- local codes = newcodes[i]
- if type(codes) == "table" then
- local method = codes[1]
- if method == "discretionary" then
- local pre, post, replace = codes[2], codes[3], codes[4]
- if pre then
- pre = tonodes(pre,last)
- end
- if post then
- post = tonodes(post,last)
- end
- if replace then
- replace = tonodes(replace,last)
- end
- -- todo: also set attr
- local new = new_disc(pre,post,replace)
- setattrlist(new,last)
- head, current = insert_after(head,current,new)
- elseif method == "noligature" then
- -- not that efficient to copy but ok for testing
- local list = codes[2]
- if list then
- for i=1,#list do
- local new = copy_node(last)
- setchar(new,list[i])
- setattr(new,a_noligature,1)
- head, current = insert_after(head,current,new)
- end
- else
- local new = copy_node(last)
- setchar(new,zwnj)
- head, current = insert_after(head,current,new)
- end
- else
- -- todo
+ -- we have a run
+ tree = trees[a]
+ if tree then
+ local char = getchar(current)
+ local punc = is_punctuation[char]
+ if mode == "punc" then
+ if not punc then
+ if root then
+ local final = root.final
+ if final then
+ head = replace(head,wordstart,wordend,final,hasspace,overload)
+ elseif prevfinal then
+ head = replace(head,wordstart,prevend,prevfinal,hasspace,overload)
end
- else
- local new = copy_node(last)
- setchar(new,codes)
- head, current = insert_after(head,current,new)
+ prevfinal = false
+ root = false
end
- i = i + 1
+ mode = "word"
end
- flush_list(list)
- -- elseif newlength == 0 then
- -- -- nothing gets replaced
- -- current = getnext(last)
- elseif oldlength == newlength then -- #old == #new
- if final.word == final.replacement then
- -- nothing to do but skip
- else
- for i=1,newlength do
- setchar(current,newcodes[i])
- current = getnext(current)
+ elseif mode == "word" then
+ if punc then
+ if root then
+ local final = root.final
+ if final then
+ head = replace(head,wordstart,wordend,final,hasspace,overload)
+ elseif prevfinal then
+ head = replace(head,wordstart,prevend,prevfinal,hasspace,overload)
+ end
+ prevfinal = false
+ root = false
end
+ mode = "punc"
end
- elseif oldlength < newlength then -- #old < #new
- for i=1,newlength-oldlength do
- local n = copy_node(current)
- setchar(n,newcodes[i])
- head, current = insert_node_before(head,current,n)
- current = getnext(current)
- end
- for i=newlength-oldlength+1,newlength do
- setchar(current,newcodes[i])
- current = getnext(current)
+ else
+ mode = punc and "punc" or "word"
+ end
+ if root then
+ root = root[char]
+ if root then
+ wordend = current
end
- else -- #old > #new or #new == 0
- for i=1,oldlength-newlength do
- head, current = remove_node(head,current,true)
+ else
+ if prevfinal then
+ head = replace(head,wordstart,prevend,prevfinal,hasspace,overload)
+ prevfinal = false
end
- for i=1,newlength do
- setchar(current,newcodes[i])
- current = getnext(current)
+ root = tree[char]
+ if root then
+ wordstart = current
+ wordend = current
+ prevend = false
+ hasspace = false
end
end
- if overload then
- overload(final,getnext(precurrent),getprev(current))
+ else
+ root= false
+ end
+ else
+ tree = false
+ end
+ current = getnext(current)
+ elseif root then
+ local final = root.final
+ if mode == "word" and id == glue_code then
+ local s = getsubtype(current)
+ if s == spaceskip_code or s == xspaceskip_code then
+ local r = root[32] -- maybe more types
+ if r then
+ if not prevend then
+ local f = root.final
+ if f then
+ prevend = wordend
+ prevfinal = f
+ end
+ end
+ wordend = current
+ root = r
+ hasspace = true
+ goto moveon
end
end
end
+ if final then
+ head, current = replace(head,wordstart,wordend,final,hasspace,overload)
+ elseif prevfinal then
+ head, current = replace(head,wordstart,prevend,prevfinal,hasspace,overload)
+ end
+ prevfinal = false
+ root = false
+ ::moveon::
+ current = getnext(current)
+ else
+ current = getnext(current)
+ end
+ end
+ if root then
+ local final = root.final
+ if final then
+ head = replace(head,wordstart,wordend,final,hasspace,overload)
+ elseif prevfinal then
+ head = replace(head,wordstart,prevend,prevfinal,hasspace,overload)
end
- -- we're one ahead now but we need to because we handle words
- current = getnext(current)
end
return head
end
diff --git a/tex/context/base/mkiv/lang-url.lua b/tex/context/base/mkiv/lang-url.lua
index 7428d64ab..7a8b7ca86 100644
--- a/tex/context/base/mkiv/lang-url.lua
+++ b/tex/context/base/mkiv/lang-url.lua
@@ -9,7 +9,9 @@ if not modules then modules = { } end modules ['lang-url'] = {
local utfcharacters, utfbyte, utfchar = utf.characters, utf.byte, utf.char
local min, max = math.min, math.max
-local context = context
+local context = context
+local ctx_pushcatcodes = context.pushcatcodes
+local ctx_popcatcodes = context.popcatcodes
local implement = interfaces.implement
local variables = interfaces.variables
@@ -190,9 +192,9 @@ local function action(hyphenatedurl,str,left,right,disc)
end
end
if dodi then
- list[i] = "\\d"
+ list[i] = "\\lang_url_d "
else
- list[i] = "\\" .. what .. "{" .. utfbyte(char) .. "}"
+ list[i] = "\\lang_url_" .. what .. "{" .. utfbyte(char) .. "}"
end
prev = char
end
@@ -200,7 +202,9 @@ local function action(hyphenatedurl,str,left,right,disc)
report("old : %s",str)
report("new : %t",list)
end
+ ctx_pushcatcodes("prtcatcodes")
context("%t",list)
+ ctx_popcatcodes()
end
-- urls.action = function(_,...) action(...) end -- sort of obsolete
diff --git a/tex/context/base/mkiv/lang-url.mkiv b/tex/context/base/mkiv/lang-url.mkiv
index 6afef63ce..c3ec02da4 100644
--- a/tex/context/base/mkiv/lang-url.mkiv
+++ b/tex/context/base/mkiv/lang-url.mkiv
@@ -47,19 +47,19 @@
\resetfontfeature
\resetcharacterspacing
%
- \let\&\letterampersand
- \let\#\letterhash
- \let\~\lettertilde
- \let\\\letterbackslash
- \let\$\letterdollar
- \let\^\letterhat
- \let\_\letterunderscore
- \let\{\letterleftbrace
- \let\}\letterrightbrace
- \let\|\letterbar
- \let~=\lettertilde
- \let|=\letterbar
- \let\Ux\eUx
+ \enforced\let\&\letterampersand
+ \enforced\let\#\letterhash
+ \enforced\let\~\lettertilde
+ \enforced\let\\\letterbackslash
+ \enforced\let\$\letterdollar
+ \enforced\let\^\letterhat
+ \enforced\let\_\letterunderscore
+ \enforced\let\{\letterleftbrace
+ \enforced\let\}\letterrightbrace
+ \enforced\let\|\letterbar
+ \enforced\let~=\lettertilde
+ \enforced\let|=\letterbar
+ \enforced\let\Ux\eUx
\to \everyhyphenatedurl
\let\hyphenatedurlseparator \empty % \periodcentered
@@ -100,22 +100,17 @@
{\dontleavehmode
\begingroup
\the\everyhyphenatedurl
- \normallanguage\zerocount
- \let\a\lang_url_a % after
- \let\b\lang_url_b % before
- \let\d\lang_url_d % disc
- \let\l\lang_url_l % letter
- \let\c\lang_url_c % character
- \let\L\lang_url_L % letter_nobreak
- \let\C\lang_url_C % character_nobreak
+ \normallanguage\zerocount % \nohyphens in mkiv
\scratchskipone\zeropoint\s!plus\dimexpr\emwidth/12\s!minus\dimexpr\emwidth/24\relax % 1.00pt @ 12pt
\scratchskiptwo\zeropoint\s!plus\dimexpr\emwidth/48\s!minus\dimexpr\emwidth/96\relax % 0.25pt @ 12pt
+ \unprotect
\normalexpanded{\noexpand\clf_hyphenatedurl
{\noexpand\detokenize{#1}}%
\hyphenatedurllefthyphenmin
\hyphenatedurlrighthyphenmin
{\hyphenatedurldiscretionary}%
}%
+ \protect
\endgroup}
%D \macros
diff --git a/tex/context/base/mkiv/lang-wrd.lua b/tex/context/base/mkiv/lang-wrd.lua
index 9fbced2ce..1c440bd7f 100644
--- a/tex/context/base/mkiv/lang-wrd.lua
+++ b/tex/context/base/mkiv/lang-wrd.lua
@@ -39,7 +39,7 @@ local getid = nuts.getid
local getchar = nuts.getchar
local setattr = nuts.setattr
----- getattr = nuts.getattr
-local getlang = nuts.getlang
+local getlanguage = nuts.getlanguage
local ischar = nuts.ischar
local nextnode = nuts.traversers.node
@@ -163,7 +163,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared
while current do
local code, id = ischar(current) -- not isglyph because otherwise we can run into
if code then -- processed streams (\about[foo] does that)
- local a = getlang(current)
+ local a = getlanguage(current)
if a then
if a ~= language then
if s > 0 then
diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua
index 45000aebc..0ff764e1d 100644
--- a/tex/context/base/mkiv/lpdf-epa.lua
+++ b/tex/context/base/mkiv/lpdf-epa.lua
@@ -510,7 +510,7 @@ local validstamps = {
ForPublicRelease = true,
}
--- todo: we can use runtoks instead of steps
+-- todo: we can use runlocal instead of steps
local function validStamp(v)
local name = "Stamped" -- fallback
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index ebce83ca8..16448c429 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -37,7 +37,7 @@ texconfig.save_size = 500000
texconfig.stack_size = 100000
texconfig.buffer_size = 10000000
texconfig.token_size = 10000000
-texconfig.node_size = 20000000
+texconfig.node_size = 50000000
texconfig.max_pool = 10000000
else
@@ -121,15 +121,17 @@ function texconfig.init()
},
basictex = {
-- always
- "callback", "font", "lang", "lua", "node", "status", "tex", "texconfig", "texio", "token",
- -- not in luametatex
- "img", "pdf",
+ "callback", "font", "lua", "node", "status", "tex", "texconfig", "texio", "token",
+ -- not in luametatex
+ "img", "pdf", "lang",
+ -- in luametatex
+ "language",
},
extralua = {
-- not in luametatex
"unicode", "utf", "gzip", "zip", "zlib",
-- in luametatex
- "xzip", "xmath", "xcomplex", "basexx",
+ "xzip", "xmath", "xcomplex", "xdecimal", "basexx",
-- maybe some day in luametatex
"lz4", "lzo",
-- always (mime can go)
diff --git a/tex/context/base/mkiv/luat-cod.lmt b/tex/context/base/mkiv/luat-cod.lmt
index 9b7564483..e4432345e 100644
--- a/tex/context/base/mkiv/luat-cod.lmt
+++ b/tex/context/base/mkiv/luat-cod.lmt
@@ -27,7 +27,7 @@ texconfig.save_size = 500000
texconfig.stack_size = 100000
texconfig.buffer_size = 10000000
texconfig.token_size = 10000000
-texconfig.node_size = 20000000
+texconfig.node_size = 50000000
texconfig.max_print_line = 100000
texconfig.max_strings = 500000
@@ -190,7 +190,7 @@ if not environment.luafilechunk then
fullname = sourcepath .. "/" .. filename
end
local data = loadfile(fullname)
- texio.write("term and log","<",data and "+ " or "- ",fullname,">")
+ texio.write("terminal_and_logfile","<",data and "+ " or "- ",fullname,">")
if data then
-- package.loaded[gsub(filename,"%..-$"] =
data()
@@ -297,7 +297,7 @@ callback.register("trace_memory", function(what,success)
logs.report("tex memory","bumping category %a %s, details: %s",
what,success,table.sequenced(status["get"..what.."state"]()))
elseif texio then
- texio.write_nl(format("bumping tex %a memory %s",
+ texio.write_nl(format("bumping tex '%s' memory %s",
what,success))
end
-- os.exit()
diff --git a/tex/context/base/mkiv/luat-cod.mkxl b/tex/context/base/mkiv/luat-cod.mkxl
index 3d3a5dd6b..fec88aecd 100644
--- a/tex/context/base/mkiv/luat-cod.mkxl
+++ b/tex/context/base/mkiv/luat-cod.mkxl
@@ -17,28 +17,28 @@
\newif\ifproductionrun
-\let\ctxdirectlua \directlua
-\let\ctxlatelua \latelua
-\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens
-\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens
-\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens
-\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens
-\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens
-\def\ctxreport #1{\directlua{logs.writer[[#1]]}}
+\permanent\let\ctxdirectlua \directlua
+\permanent\let\ctxlatelua \latelua
+\permanent\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens
+\permanent\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens
+\permanent\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens
+\permanent\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens
+\permanent\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens
+\permanent\def\ctxreport #1{\directlua{logs.writer[[#1]]}}
%D Take your choice \unknown
-\let\ctxlua \ctxdirectlua
-\let\luacode \ctxdirectlua
-\let\lateluacode \ctxlatelua
-\let\directluacode\ctxdirectlua
+\aliased\let\ctxlua \ctxdirectlua
+\aliased\let\luacode \ctxdirectlua
+\aliased\let\lateluacode \ctxlatelua
+\aliased\let\directluacode\ctxdirectlua
%D Reporting the version of \LUA\ that we use is done as follows:
-\def\luaversion{\ctxwrite{LUAVERSION}}
+\permanent\def\luaversion{\ctxwrite{LUAVERSION}}
-\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}}
-\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}}
+\permanent\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}}
+\permanent\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}}
\registerctxluafile{luat-cod.lmt}{autosuffix}
diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua
index 815ff10db..30792931e 100644
--- a/tex/context/base/mkiv/luat-fmt.lua
+++ b/tex/context/base/mkiv/luat-fmt.lua
@@ -178,8 +178,9 @@ function environment.make_format(formatname)
-- because we can have half qualified paths (in lxc)
local binarypath = validbinarypath()
report_format("changing to format path %a",validformatpath)
- lfs.chdir(validformatpath)
- if dir.current() ~= validformatpath then
+ -- lfs.chdir(validformatpath)
+ -- if dir.current() ~= validformatpath then
+ if not lfs.chdir(validformatpath) then
return fatalerror(startupdir,"unable to change to format path %a",validformatpath)
end
-- now we can generate the format, where we use a couple of flags,
diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv
index d1b02ec7e..053e2ea4d 100644
--- a/tex/context/base/mkiv/luat-ini.mkiv
+++ b/tex/context/base/mkiv/luat-ini.mkiv
@@ -77,21 +77,25 @@
\edef\lua_letter_seven {\string\7} \edef\lua_letter_eight {\string\8}
\edef\lua_letter_nine {\string\9} \edef\lua_letter_zero {\string\0}
+\pushoverloadmode
+ \let\-\explicitdiscretionary
+\popoverloadmode
+
\everyluacode {% \appendtoks
- \let\\\lua_letter_backslash
- \let\|\lua_letter_bar \let\-\lua_letter_dash
- \let\(\lua_letter_lparent \let\)\lua_letter_rparent
- \let\{\lua_letter_lbrace \let\}\lua_letter_rbrace
- \let\'\lua_letter_squote \let\"\lua_letter_dquote
- \let\n\lua_letter_n \let\r\lua_letter_r
- \let\f\lua_letter_f \let\t\lua_letter_t
- \let\a\lua_letter_a \let\b\lua_letter_b
- \let\v\lua_letter_v \let\s\lua_letter_s
- \let\1\lua_letter_one \let\2\lua_letter_two
- \let\3\lua_letter_three \let\4\lua_letter_four
- \let\5\lua_letter_five \let\6\lua_letter_six
- \let\7\lua_letter_seven \let\8\lua_letter_eight
- \let\9\lua_letter_nine \let\0\lua_letter_zero
+ \enforced\let\\\lua_letter_backslash
+ \enforced\let\|\lua_letter_bar \enforced\let\-\lua_letter_dash
+ \enforced\let\(\lua_letter_lparent \enforced\let\)\lua_letter_rparent
+ \enforced\let\{\lua_letter_lbrace \enforced\let\}\lua_letter_rbrace
+ \enforced\let\'\lua_letter_squote \enforced\let\"\lua_letter_dquote
+ \enforced\let\n\lua_letter_n \enforced\let\r\lua_letter_r
+ \enforced\let\f\lua_letter_f \enforced\let\t\lua_letter_t
+ \enforced\let\a\lua_letter_a \enforced\let\b\lua_letter_b
+ \enforced\let\v\lua_letter_v \enforced\let\s\lua_letter_s
+ \enforced\let\1\lua_letter_one \enforced\let\2\lua_letter_two
+ \enforced\let\3\lua_letter_three \enforced\let\4\lua_letter_four
+ \enforced\let\5\lua_letter_five \enforced\let\6\lua_letter_six
+ \enforced\let\7\lua_letter_seven \enforced\let\8\lua_letter_eight
+ \enforced\let\9\lua_letter_nine \enforced\let\0\lua_letter_zero
} % \to \everyluacode
\protected\def\obeyluatokens
diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv
index ac60374d0..e89747de7 100644
--- a/tex/context/base/mkiv/luat-lib.mkiv
+++ b/tex/context/base/mkiv/luat-lib.mkiv
@@ -24,7 +24,7 @@
\registerctxluafile{util-dim}{}
\registerctxluafile{trac-set}{}
-\registerctxluafile{trac-log}{}
+\registerctxluafile{luat-log}{autosuffix}
\registerctxluafile{trac-inf}{autosuffix}
\registerctxluafile{util-lua}{}
\registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv
@@ -99,8 +99,8 @@
\registerctxluafile{lxml-aux}{}
\registerctxluafile{lxml-mis}{}
-\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}}
-\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}}
-\protected\def\writeline {\ctxlua{logs.newline()}}
+\frozen\overloaded\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}}
+\frozen\overloaded\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}}
+\frozen\overloaded\protected\def\writeline {\ctxlua{logs.newline()}}
\endinput
diff --git a/tex/context/base/mkiv/luat-log.lmt b/tex/context/base/mkiv/luat-log.lmt
new file mode 100644
index 000000000..684b2ac8d
--- /dev/null
+++ b/tex/context/base/mkiv/luat-log.lmt
@@ -0,0 +1,739 @@
+if not modules then modules = { } end modules ['luat-log'] = {
+ version = 1.001,
+ comment = "companion to trac-log.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- In fact all writes could go through lua and we could write the console and
+-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go.
+
+-- This used to be combined in trac-log but as we also split between mkiv and lmtx
+-- we now have dedicated files. A side effect is a smaller format and a smaller
+-- mtxrun.
+--
+-- We use different targets: "terminal" "logfile", "both" and have no number
+-- channel.
+
+local next, type, select, print = next, type, select, print
+local format, gmatch, find = string.format, string.gmatch, string.find
+local concat, insert, remove = table.concat, table.insert, table.remove
+local topattern = string.topattern
+local utfchar = utf.char
+local datetime = os.date
+local openfile = io.open
+
+local write_nl = texio.write_nl
+local write = texio.write
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local settings_to_hash = utilities.parsers.settings_to_hash
+local sortedkeys = table.sortedkeys
+
+-- variant is set now
+
+local variant = "default"
+----- variant = "ansi"
+
+logs = logs or { }
+local logs = logs
+
+-- we extend the formatters:
+
+formatters.add (
+ formatters, "unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+
+formatters.add (
+ formatters, "chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+
+-- basic loggers
+
+local function ignore() end
+
+setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
+
+local report, subreport, status, settarget, setformats, settranslations
+
+local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline
+
+-- we use formatters but best check for % then because for simple messages but
+-- we don't want this overhead for single messages (not that there are that
+-- many; we could have a special weak table)
+
+local function ansisupported(specification)
+ if specification ~= "ansi" and specification ~= "ansilog" then
+ return false
+ elseif os and os.enableansi then
+ return os.enableansi()
+ else
+ return false
+ end
+end
+
+do
+
+ if arg and ansisupported then
+ -- we're don't have environment.arguments yet
+ for k, v in next, arg do -- k can be negative !
+ if v == "--ansi" or v == "--c:ansi" then
+ if ansisupported("ansi") then
+ variant = "ansi"
+ end
+ break
+ elseif v == "--ansilog" or v == "--c:ansilog" then
+ if ansisupported("ansilog") then
+ variant = "ansilog"
+ end
+ break
+ end
+ end
+ end
+
+ local whereto = "both"
+ local target = nil
+ local targets = nil
+
+ local formats = table.setmetatableindex("self")
+ local translations = table.setmetatableindex("self")
+
+ local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes
+ local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop
+
+ local variants = {
+ default = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = setmetatableindex( {
+ logfile = "logfile",
+ log = "logfile",
+ file = "logfile",
+ console = "terminal",
+ terminal = "terminal",
+ both = "terminal_and_logfile",
+ }, function(t,k) t[k] = "terminal_and_logfile" end),
+ },
+ ansi = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = setmetatableindex( {
+ logfile = false,
+ log = false,
+ file = false,
+ console = "terminal",
+ terminal = "terminal",
+ both = "terminal",
+ }, function(t,k) t[k] = "terminal" end),
+ }
+ }
+
+ variants.ansilog = {
+ formats = variants.ansi.formats,
+ targets = variants.default.targets,
+ }
+
+ logs.flush = io.flush
+
+ writer = function(...)
+ if target then
+ write_nl(target,...)
+ end
+ end
+
+ newline = function()
+ if target then
+ write_nl(target,"\n")
+ end
+ end
+
+ report = function(a,b,c,...)
+ if not target then
+ -- ignore
+ elseif c ~= nil then
+ write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,report_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,report_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ direct = function(a,b,c,...)
+ if not target then
+ return ""
+ elseif c ~= nil then
+ return direct_yes(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return direct_yes(translations[a],formats[b])
+ elseif a then
+ return direct_nop(translations[a])
+ else
+ return ""
+ end
+ end
+
+ subreport = function(a,s,b,c,...)
+ if not target then
+ -- ignore
+ elseif c ~= nil then
+ write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,subreport_nop(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ subdirect = function(a,s,b,c,...)
+ if not target then
+ return ""
+ elseif c ~= nil then
+ return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return subdirect_yes(translations[a],translations[s],formats[b])
+ elseif a then
+ return subdirect_nop(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+
+ status = function(a,b,c,...)
+ if not target then
+ -- ignore
+ elseif c ~= nil then
+ write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,status_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,status_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ settarget = function(askedwhereto)
+ whereto = askedwhereto or whereto or "both"
+ target = targets[whereto]
+ if not target then
+ whereto = "both"
+ target = targets[whereto]
+ end
+ if target == "terminal" or target == "terminal_and_logfile" then
+ logs.flush = io.flush
+ else
+ logs.flush = ignore
+ end
+ end
+
+ local stack = { }
+
+ pushtarget = function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+
+ poptarget = function()
+ if #stack > 0 then
+ settarget(remove(stack))
+ end
+ end
+
+ setformats = function(f)
+ formats = f
+ end
+
+ settranslations = function(t)
+ translations = t
+ end
+
+ setprocessor = function(f)
+ local writeline = write_nl
+ write_nl = function(target,...)
+ if target then
+ writeline(target,f(...))
+ end
+ end
+ end
+
+ setformatters = function(specification)
+ local t = nil
+ local f = nil
+ local d = variants.default
+ if not specification then
+ --
+ elseif type(specification) == "table" then
+ t = specification.targets
+ f = specification.formats or specification
+ else
+ if not ansisupported(specification) then
+ specification = "default"
+ end
+ local v = variants[specification]
+ if v then
+ t = v.targets
+ f = v.formats
+ variant = specification
+ end
+ end
+ targets = t or d.targets
+ target = targets[whereto]
+ if f then
+ d = d.formats
+ else
+ f = d.formats
+ d = f
+ end
+ setmetatableindex(f,d)
+ report_yes = f.report_yes
+ report_nop = f.report_nop
+ subreport_yes = f.subreport_yes
+ subreport_nop = f.subreport_nop
+ direct_yes = f.direct_yes
+ direct_nop = f.direct_nop
+ subdirect_yes = f.subdirect_yes
+ subdirect_nop = f.subdirect_nop
+ status_yes = f.status_yes
+ status_nop = f.status_nop
+ settarget(whereto)
+ end
+
+ setformatters(variant)
+
+ setlogfile = ignore
+ settimedlog = ignore
+
+end
+
+logs.report = report
+logs.subreport = subreport
+logs.status = status
+logs.settarget = settarget
+logs.pushtarget = pushtarget
+logs.poptarget = poptarget
+logs.setformats = setformats
+logs.settranslations = settranslations
+
+logs.setlogfile = setlogfile
+logs.settimedlog = settimedlog
+logs.setprocessor = setprocessor
+logs.setformatters = setformatters
+
+logs.direct = direct
+logs.subdirect = subdirect
+logs.writer = writer
+logs.newline = newline
+
+local data = { }
+local states = nil
+local force = false
+
+function logs.reporter(category,subcategory)
+ local logger = data[category]
+ if not logger then
+ local state = states == true
+ if not state and type(states) == "table" then
+ for c, _ in next, states do
+ if find(category,c) then
+ state = true
+ break
+ end
+ end
+ end
+ logger = {
+ reporters = { },
+ state = state,
+ }
+ data[category] = logger
+ end
+ local reporter = logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter = function(...)
+ if force or not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory] = reporter
+ else
+ local tag = category
+ reporter = function(...)
+ if force or not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default = reporter
+ end
+ end
+ return reporter
+end
+
+logs.new = logs.reporter -- for old times sake
+
+-- context specicific: this ends up in the macro stream
+
+local ctxreport = logs.writer
+
+function logs.setmessenger(m)
+ ctxreport = m
+end
+
+function logs.messenger(category,subcategory)
+ -- we need to avoid catcode mess (todo: fast context)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
+end
+
+-- so far
+
+local function setblocked(category,value) -- v.state == value == true : disable
+ if category == true or category == "all" then
+ -- lock all
+ category, value = "*", true
+ elseif category == false then
+ -- unlock all
+ category, value = "*", false
+ elseif value == nil then
+ -- lock selective
+ value = true
+ end
+ if category == "*" then
+ states = value
+ for k, v in next, data do
+ v.state = value
+ end
+ else
+ alllocked = false
+ states = settings_to_hash(category,type(states)=="table" and states or nil)
+ for c in next, states do
+ local v = data[c]
+ if v then
+ v.state = value
+ else
+ c = topattern(c,true,true)
+ for k, v in next, data do
+ if find(k,c) then
+ v.state = value
+ end
+ end
+ end
+ end
+ end
+end
+
+function logs.disable(category,value)
+ setblocked(category,value == nil and true or value)
+end
+
+function logs.enable(category)
+ setblocked(category,false)
+end
+
+function logs.categories()
+ return sortedkeys(data)
+end
+
+function logs.show()
+ local n, c, s, max = 0, 0, 0, 0
+ for category, v in table.sortedpairs(data) do
+ n = n + 1
+ local state = v.state
+ local reporters = v.reporters
+ local nc = #category
+ if nc > c then
+ c = nc
+ end
+ for subcategory, _ in next, reporters do
+ local ns = #subcategory
+ if ns > c then
+ s = ns
+ end
+ local m = nc + ns
+ if m > max then
+ max = m
+ end
+ end
+ local subcategories = concat(sortedkeys(reporters),", ")
+ if state == true then
+ state = "disabled"
+ elseif state == false then
+ state = "enabled"
+ else
+ state = "unknown"
+ end
+ -- no new here
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
+end
+
+local delayed_reporters = { }
+
+setmetatableindex(delayed_reporters,function(t,k)
+ local v = logs.reporter(k.name)
+ t[k] = v
+ return v
+end)
+
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
+end
+
+directives.register("logs.blocked", function(v)
+ setblocked(v,true)
+end)
+
+directives.register("logs.target", function(v)
+ settarget(v)
+end)
+
+do
+
+ local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
+ local texgetcount = tex and tex.getcount
+
+ local real, user, sub = 0, 0, 0
+
+ function logs.start_page_number()
+ real = texgetcount("realpageno")
+ user = texgetcount("userpageno")
+ sub = texgetcount("subpageno")
+ end
+
+ local timing = false
+ local usage = false
+ local lasttime = nil
+
+ logs.private = {
+ enablepagetiming = function()
+ usage = true
+ end,
+ getpagetiming = function()
+ return type(usage) == "table" and usage
+ end,
+ }
+
+ trackers.register("pages.timing", function() timing = "" end)
+
+ function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing or usage then
+ local elapsed = statistics.currenttime(statistics)
+ local average, page
+ if not lasttime or real < 2 then
+ average = elapsed
+ page = elapsed
+ else
+ average = elapsed / (real - 1)
+ page = elapsed - lasttime
+ end
+ lasttime = elapsed
+ if timing then
+ timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
+ end
+ if usage then
+ usage = {
+ page = {
+ real = real,
+ user = user,
+ sub = sub,
+ },
+ time = {
+ elapsed = elapsed,
+ page = page,
+ average = average,
+ }
+ }
+ end
+ end
+ if real <= 0 then
+ report("flushing page%s",timing)
+ elseif user <= 0 then
+ report("flushing realpage %s%s",real,timing)
+ elseif sub <= 0 then
+ report("flushing realpage %s, userpage %s%s",real,user,timing)
+ else
+ report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
+ end
+ logs.flush()
+ end
+
+end
+
+-- we don't have show_open and show_close callbacks yet
+
+do
+ local texerror = tex and tex.error or print
+ local formatters = string.formatters
+
+ function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here
+ texerror(first and formatters[fmt](first,...) or fmt)
+ end
+
+end
+
+-- this is somewhat slower but prevents out-of-order messages when print is mixed
+-- with texio.write
+
+-- io.stdout:setvbuf('no')
+-- io.stderr:setvbuf('no')
+
+-- windows: > nul 2>&1
+-- unix : > null 2>&1
+
+if package.helpers.report then
+ package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun
+end
+
+do
+
+ local finalactions = { }
+ local fatalerrors = { }
+ local possiblefatal = { }
+ local loggingerrors = false
+
+ function logs.loggingerrors()
+ return loggingerrors
+ end
+
+ directives.register("logs.errors",function(v)
+ loggingerrors = v
+ if type(v) == "string" then
+ fatalerrors = settings_to_hash(v)
+ else
+ fatalerrors = { }
+ end
+ end)
+
+ function logs.registerfinalactions(...)
+ insert(finalactions,...) -- so we can force an order if needed
+ end
+
+ local what = nil
+ local report = nil
+ local state = nil
+ local target = nil
+
+ local function startlogging(t,r,w,s)
+ target = t
+ state = force
+ force = true
+ report = type(r) == "function" and r or logs.reporter(r)
+ what = w
+ pushtarget(target)
+ newline()
+ if s then
+ report("start %s: %s",what,s)
+ else
+ report("start %s",what)
+ end
+ if target == "logfile" then
+ newline()
+ end
+ return report
+ end
+
+ local function stoplogging()
+ if target == "logfile" then
+ newline()
+ end
+ report("stop %s",what)
+ if target == "logfile" then
+ newline()
+ end
+ poptarget()
+ state = oldstate
+ end
+
+ function logs.startfilelogging(...)
+ return startlogging("logfile", ...)
+ end
+
+ logs.stopfilelogging = stoplogging
+
+ local done = false
+
+ function logs.starterrorlogging(r,w,...)
+ if not done then
+ pushtarget("terminal")
+ newline()
+ logs.report("error logging","start possible issues")
+ poptarget()
+ done = true
+ end
+ if fatalerrors[w] then
+ possiblefatal[w] = true
+ end
+ return startlogging("terminal",r,w,...)
+ end
+
+ logs.stoperrorlogging = stoplogging
+
+ function logs.finalactions()
+ if #finalactions > 0 then
+ for i=1,#finalactions do
+ finalactions[i]()
+ end
+ if done then
+ pushtarget("terminal")
+ newline()
+ logs.report("error logging","stop possible issues")
+ poptarget()
+ end
+ return next(possiblefatal) and sortedkeys(possiblefatal) or false
+ end
+ end
+
+end
+
+-- just in case we load from context
+
+local dummy = function() end
+
+function logs.application(t)
+ return {
+ name = t.name or tex.jobname,
+ banner = t.banner,
+ report = logs.reporter(t.name),
+ moreinfo = dummy,
+ export = dummy,
+ help = dummy,
+ identify = dummy,
+ version = dummy,
+ }
+end
diff --git a/tex/context/base/mkiv/luat-log.lua b/tex/context/base/mkiv/luat-log.lua
new file mode 100644
index 000000000..fd3b73d3d
--- /dev/null
+++ b/tex/context/base/mkiv/luat-log.lua
@@ -0,0 +1,795 @@
+if not modules then modules = { } end modules ['luat-log'] = {
+ version = 1.001,
+ comment = "companion to trac-log.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- In fact all writes could go through lua and we could write the console and
+-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go.
+
+-- This used to be combined in trac-log but as we also split between mkiv and lmtx
+-- we now have dedicated files. A side effect is a smaller format and a smaller
+-- mtxrun.
+
+local next, type, select, print = next, type, select, print
+local format, gmatch, find = string.format, string.gmatch, string.find
+local concat, insert, remove = table.concat, table.insert, table.remove
+local topattern = string.topattern
+local utfchar = utf.char
+local datetime = os.date
+local openfile = io.open
+
+local write_nl = texio and texio.write_nl
+local write = texio and texio.write
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local settings_to_hash = utilities.parsers.settings_to_hash
+local sortedkeys = table.sortedkeys
+
+-- variant is set now
+
+local variant = "default"
+----- variant = "ansi"
+
+logs = logs or { }
+local logs = logs
+
+-- we extend the formatters:
+
+formatters.add (
+ formatters, "unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+
+formatters.add (
+ formatters, "chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+
+-- basic loggers
+
+local function ignore() end
+
+setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
+
+local report, subreport, status, settarget, setformats, settranslations
+
+local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline
+
+-- we use formatters but best check for % then because for simple messages but
+-- we don't want this overhead for single messages (not that there are that
+-- many; we could have a special weak table)
+
+local function ansisupported(specification)
+ if specification ~= "ansi" and specification ~= "ansilog" then
+ return false
+ elseif os and os.enableansi then
+ return os.enableansi()
+ else
+ return false
+ end
+end
+
+do
+
+ if texio.setescape then
+ texio.setescape(0) -- or (false)
+ end
+
+ if arg and ansisupported then
+ -- we're don't have environment.arguments yet
+ for k, v in next, arg do -- k can be negative !
+ if v == "--ansi" or v == "--c:ansi" then
+ if ansisupported("ansi") then
+ variant = "ansi"
+ end
+ break
+ elseif v == "--ansilog" or v == "--c:ansilog" then
+ if ansisupported("ansilog") then
+ variant = "ansilog"
+ end
+ break
+ end
+ end
+ end
+
+ local function useluawrites()
+
+ -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2)
+ -- still needed for luajittex .. luatex should not have that ^^ mess
+
+ local texio_write_nl = texio.write_nl
+ local texio_write = texio.write
+ local io_write = io.write
+
+ write_nl = function(target,...)
+ if not io_write then
+ io_write = io.write
+ end
+ if target == "term and log" then
+ texio_write_nl("log",...)
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target == "log" then
+ texio_write_nl("log",...)
+ elseif target == "term" then
+ texio_write_nl("term","")
+ io_write(...)
+ elseif type(target) == "number" then
+ texio_write_nl(target,...) -- a tex output channel
+ elseif target ~= "none" then
+ texio_write_nl("log",target,...)
+ texio_write_nl("term","")
+ io_write(target,...)
+ end
+ end
+
+ write = function(target,...)
+ if not io_write then
+ io_write = io.write
+ end
+ if target == "term and log" then
+ texio_write("log",...)
+ io_write(...)
+ elseif target == "log" then
+ texio_write("log",...)
+ elseif target == "term" then
+ io_write(...)
+ elseif type(target) == "number" then
+ texio_write(target,...) -- a tex output channel
+ elseif target ~= "none" then
+ texio_write("log",target,...)
+ io_write(target,...)
+ end
+ end
+
+ texio.write = write
+ texio.write_nl = write_nl
+
+ useluawrites = ignore
+
+ end
+
+ -- local format = string.formatter
+
+ local whereto = "both"
+ local target = nil
+ local targets = nil
+
+ local formats = table.setmetatableindex("self")
+ local translations = table.setmetatableindex("self")
+
+ local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes
+ local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop
+
+ local variants = {
+ default = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = {
+ logfile = "log",
+ log = "log",
+ file = "log",
+ console = "term",
+ terminal = "term",
+ both = "term and log",
+ },
+ },
+ ansi = {
+ formats = {
+ report_yes = formatters["%-15s > %s\n"],
+ report_nop = formatters["%-15s >\n"],
+ direct_yes = formatters["%-15s > %s"],
+ direct_nop = formatters["%-15s >"],
+ subreport_yes = formatters["%-15s > %s > %s\n"],
+ subreport_nop = formatters["%-15s > %s >\n"],
+ subdirect_yes = formatters["%-15s > %s > %s"],
+ subdirect_nop = formatters["%-15s > %s >"],
+ status_yes = formatters["%-15s : %s\n"],
+ status_nop = formatters["%-15s :\n"],
+ },
+ targets = {
+ logfile = "none",
+ log = "none",
+ file = "none",
+ console = "term",
+ terminal = "term",
+ both = "term",
+ },
+ }
+ }
+
+ variants.ansilog = {
+ formats = variants.ansi.formats,
+ targets = variants.default.targets,
+ }
+
+ logs.flush = io.flush
+
+ writer = function(...)
+ write_nl(target,...)
+ end
+
+ newline = function()
+ write_nl(target,"\n")
+ end
+
+ report = function(a,b,c,...)
+ if c ~= nil then
+ write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,report_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,report_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ direct = function(a,b,c,...)
+ if c ~= nil then
+ return direct_yes(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return direct_yes(translations[a],formats[b])
+ elseif a then
+ return direct_nop(translations[a])
+ else
+ return ""
+ end
+ end
+
+ subreport = function(a,s,b,c,...)
+ if c ~= nil then
+ write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,subreport_nop(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ subdirect = function(a,s,b,c,...)
+ if c ~= nil then
+ return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return subdirect_yes(translations[a],translations[s],formats[b])
+ elseif a then
+ return subdirect_nop(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+
+ status = function(a,b,c,...)
+ if c ~= nil then
+ write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,status_yes(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,status_nop(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+
+ settarget = function(askedwhereto)
+ whereto = askedwhereto or whereto or "both"
+ target = targets[whereto]
+ if not target then
+ whereto = "both"
+ target = targets[whereto]
+ end
+ if target == "term" or target == "term and log" then
+ logs.flush = io.flush
+ else
+ logs.flush = ignore
+ end
+ end
+
+ local stack = { }
+
+ pushtarget = function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+
+ poptarget = function()
+ if #stack > 0 then
+ settarget(remove(stack))
+ end
+ end
+
+ setformats = function(f)
+ formats = f
+ end
+
+ settranslations = function(t)
+ translations = t
+ end
+
+ setprocessor = function(f)
+ local writeline = write_nl
+ write_nl = function(target,...)
+ writeline(target,f(...))
+ end
+ end
+
+ setformatters = function(specification)
+ local t = nil
+ local f = nil
+ local d = variants.default
+ if not specification then
+ --
+ elseif type(specification) == "table" then
+ t = specification.targets
+ f = specification.formats or specification
+ else
+ if not ansisupported(specification) then
+ specification = "default"
+ end
+ local v = variants[specification]
+ if v then
+ t = v.targets
+ f = v.formats
+ variant = specification
+ end
+ end
+ targets = t or d.targets
+ target = targets[whereto] or target
+ if f then
+ d = d.formats
+ else
+ f = d.formats
+ d = f
+ end
+ setmetatableindex(f,d)
+ report_yes = f.report_yes
+ report_nop = f.report_nop
+ subreport_yes = f.subreport_yes
+ subreport_nop = f.subreport_nop
+ direct_yes = f.direct_yes
+ direct_nop = f.direct_nop
+ subdirect_yes = f.subdirect_yes
+ subdirect_nop = f.subdirect_nop
+ status_yes = f.status_yes
+ status_nop = f.status_nop
+ if variant == "ansi" or variant == "ansilog" then
+ useluawrites() -- because tex escapes ^^, not needed in lmtx
+ end
+ settarget(whereto)
+ end
+
+ setformatters(variant)
+
+ setlogfile = ignore
+ settimedlog = ignore
+
+ -- settimedlog = function()
+ -- local localtime = os.localtime
+ -- local writeline = write_nl
+ -- write_nl = function(f,...)
+ -- writeline(f,localtime() .. " | " .. concat { ... })
+ -- end
+ -- settimedlog = ignore
+ -- end
+
+end
+
+logs.report = report
+logs.subreport = subreport
+logs.status = status
+logs.settarget = settarget
+logs.pushtarget = pushtarget
+logs.poptarget = poptarget
+logs.setformats = setformats
+logs.settranslations = settranslations
+
+logs.setlogfile = setlogfile
+logs.settimedlog = settimedlog
+logs.setprocessor = setprocessor
+logs.setformatters = setformatters
+
+logs.direct = direct
+logs.subdirect = subdirect
+logs.writer = writer
+logs.newline = newline
+
+local data = { }
+local states = nil
+local force = false
+
+function logs.reporter(category,subcategory)
+ local logger = data[category]
+ if not logger then
+ local state = states == true
+ if not state and type(states) == "table" then
+ for c, _ in next, states do
+ if find(category,c) then
+ state = true
+ break
+ end
+ end
+ end
+ logger = {
+ reporters = { },
+ state = state,
+ }
+ data[category] = logger
+ end
+ local reporter = logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter = function(...)
+ if force or not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory] = reporter
+ else
+ local tag = category
+ reporter = function(...)
+ if force or not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default = reporter
+ end
+ end
+ return reporter
+end
+
+logs.new = logs.reporter -- for old times sake
+
+-- context specicific: this ends up in the macro stream
+
+local ctxreport = logs.writer
+
+function logs.setmessenger(m)
+ ctxreport = m
+end
+
+function logs.messenger(category,subcategory)
+ -- we need to avoid catcode mess (todo: fast context)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
+end
+
+-- so far
+
+local function setblocked(category,value) -- v.state == value == true : disable
+ if category == true or category == "all" then
+ -- lock all
+ category, value = "*", true
+ elseif category == false then
+ -- unlock all
+ category, value = "*", false
+ elseif value == nil then
+ -- lock selective
+ value = true
+ end
+ if category == "*" then
+ states = value
+ for k, v in next, data do
+ v.state = value
+ end
+ else
+ alllocked = false
+ states = settings_to_hash(category,type(states)=="table" and states or nil)
+ for c in next, states do
+ local v = data[c]
+ if v then
+ v.state = value
+ else
+ c = topattern(c,true,true)
+ for k, v in next, data do
+ if find(k,c) then
+ v.state = value
+ end
+ end
+ end
+ end
+ end
+end
+
+function logs.disable(category,value)
+ setblocked(category,value == nil and true or value)
+end
+
+function logs.enable(category)
+ setblocked(category,false)
+end
+
+function logs.categories()
+ return sortedkeys(data)
+end
+
+function logs.show()
+ local n, c, s, max = 0, 0, 0, 0
+ for category, v in table.sortedpairs(data) do
+ n = n + 1
+ local state = v.state
+ local reporters = v.reporters
+ local nc = #category
+ if nc > c then
+ c = nc
+ end
+ for subcategory, _ in next, reporters do
+ local ns = #subcategory
+ if ns > c then
+ s = ns
+ end
+ local m = nc + ns
+ if m > max then
+ max = m
+ end
+ end
+ local subcategories = concat(sortedkeys(reporters),", ")
+ if state == true then
+ state = "disabled"
+ elseif state == false then
+ state = "enabled"
+ else
+ state = "unknown"
+ end
+ -- no new here
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
+end
+
+local delayed_reporters = { }
+
+setmetatableindex(delayed_reporters,function(t,k)
+ local v = logs.reporter(k.name)
+ t[k] = v
+ return v
+end)
+
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
+end
+
+directives.register("logs.blocked", function(v)
+ setblocked(v,true)
+end)
+
+directives.register("logs.target", function(v)
+ settarget(v)
+end)
+
+do
+
+ local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
+ local texgetcount = tex and tex.getcount
+
+ local real, user, sub = 0, 0, 0
+
+ function logs.start_page_number()
+ real = texgetcount("realpageno")
+ user = texgetcount("userpageno")
+ sub = texgetcount("subpageno")
+ end
+
+ local timing = false
+ local usage = false
+ local lasttime = nil
+
+ logs.private = {
+ enablepagetiming = function()
+ usage = true
+ end,
+ getpagetiming = function()
+ return type(usage) == "table" and usage
+ end,
+ }
+
+ trackers.register("pages.timing", function() timing = "" end)
+
+ function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing or usage then
+ local elapsed = statistics.currenttime(statistics)
+ local average, page
+ if not lasttime or real < 2 then
+ average = elapsed
+ page = elapsed
+ else
+ average = elapsed / (real - 1)
+ page = elapsed - lasttime
+ end
+ lasttime = elapsed
+ if timing then
+ timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
+ end
+ if usage then
+ usage = {
+ page = {
+ real = real,
+ user = user,
+ sub = sub,
+ },
+ time = {
+ elapsed = elapsed,
+ page = page,
+ average = average,
+ }
+ }
+ end
+ end
+ if real <= 0 then
+ report("flushing page%s",timing)
+ elseif user <= 0 then
+ report("flushing realpage %s%s",real,timing)
+ elseif sub <= 0 then
+ report("flushing realpage %s, userpage %s%s",real,user,timing)
+ else
+ report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
+ end
+ logs.flush()
+ end
+
+end
+
+-- we don't have show_open and show_close callbacks yet
+
+do
+ local texerror = tex and tex.error or print
+ local formatters = string.formatters
+
+ function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here
+ texerror(first and formatters[fmt](first,...) or fmt)
+ end
+
+end
+
+-- this is somewhat slower but prevents out-of-order messages when print is mixed
+-- with texio.write
+
+-- io.stdout:setvbuf('no')
+-- io.stderr:setvbuf('no')
+
+-- windows: > nul 2>&1
+-- unix : > null 2>&1
+
+if package.helpers.report then
+ package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun
+end
+
+do
+
+ local finalactions = { }
+ local fatalerrors = { }
+ local possiblefatal = { }
+ local loggingerrors = false
+
+ function logs.loggingerrors()
+ return loggingerrors
+ end
+
+ directives.register("logs.errors",function(v)
+ loggingerrors = v
+ if type(v) == "string" then
+ fatalerrors = settings_to_hash(v)
+ else
+ fatalerrors = { }
+ end
+ end)
+
+ function logs.registerfinalactions(...)
+ insert(finalactions,...) -- so we can force an order if needed
+ end
+
+ local what = nil
+ local report = nil
+ local state = nil
+ local target = nil
+
+ local function startlogging(t,r,w,s)
+ target = t
+ state = force
+ force = true
+ report = type(r) == "function" and r or logs.reporter(r)
+ what = w
+ pushtarget(target)
+ newline()
+ if s then
+ report("start %s: %s",what,s)
+ else
+ report("start %s",what)
+ end
+ if target == "logfile" then
+ newline()
+ end
+ return report
+ end
+
+ local function stoplogging()
+ if target == "logfile" then
+ newline()
+ end
+ report("stop %s",what)
+ if target == "logfile" then
+ newline()
+ end
+ poptarget()
+ state = oldstate
+ end
+
+ function logs.startfilelogging(...)
+ return startlogging("logfile", ...)
+ end
+
+ logs.stopfilelogging = stoplogging
+
+ local done = false
+
+ function logs.starterrorlogging(r,w,...)
+ if not done then
+ pushtarget("terminal")
+ newline()
+ logs.report("error logging","start possible issues")
+ poptarget()
+ done = true
+ end
+ if fatalerrors[w] then
+ possiblefatal[w] = true
+ end
+ return startlogging("terminal",r,w,...)
+ end
+
+ logs.stoperrorlogging = stoplogging
+
+ function logs.finalactions()
+ if #finalactions > 0 then
+ for i=1,#finalactions do
+ finalactions[i]()
+ end
+ if done then
+ pushtarget("terminal")
+ newline()
+ logs.report("error logging","stop possible issues")
+ poptarget()
+ end
+ return next(possiblefatal) and sortedkeys(possiblefatal) or false
+ end
+ end
+
+end
+
+-- just in case we load from context
+
+local dummy = function() end
+
+function logs.application(t)
+ return {
+ name = t.name or tex.jobname,
+ banner = t.banner,
+ report = logs.reporter(t.name),
+ moreinfo = dummy,
+ export = dummy,
+ help = dummy,
+ identify = dummy,
+ version = dummy,
+ }
+end
diff --git a/tex/context/base/mkiv/luat-mac.lua b/tex/context/base/mkiv/luat-mac.lua
index c754f602c..3c50a41f8 100644
--- a/tex/context/base/mkiv/luat-mac.lua
+++ b/tex/context/base/mkiv/luat-mac.lua
@@ -72,23 +72,60 @@ local stack, top, n, hashes = { }, nil, 0, { }
-- end
-- end
-local function set(s)
- if top then
- local ns = #stack
- local h = hashes[ns]
- if not h then
- h = rep("#",2^(ns-1))
- hashes[ns] = h
+local set = CONTEXTLMTXMODE > 0 and
+ function(s)
+ if top then
+ local ns = #stack
+ local h = hashes[ns]
+ if not h then
+ h = rep("#",2^(ns-1))
+ hashes[ns] = h
+ end
+ if s == "ignore" then
+ return h .. "-"
+ elseif s == "spacer" then
+ return h .. "*"
+ elseif s == "pickup" then
+ return h .. ":"
+ else
+ n = n + 1
+ if n > 9 then
+ report_macros("number of arguments > 9, ignoring %s",s)
+ elseif s == "discard" then
+ top[s] = ""
+ return h .. "0"
+ elseif s == "keepbraces" then
+ top[s] = ""
+ return h .. "+"
+ elseif s == "mandate" then
+ top[s] = ""
+ return h .. "="
+ elseif s == "keepmandate" then
+ top[s] = ""
+ return h .. "_"
+ elseif s == "prunespacing" then
+ top[s] = ""
+ return h .. "/"
+ else
+ local m = h .. n
+ top[s] = m
+ return m
+ end
+ end
end
- if s == "ignore" then
- return h .. "-"
- else
+ end
+or
+ function(s)
+ if top then
+ local ns = #stack
+ local h = hashes[ns]
+ if not h then
+ h = rep("#",2^(ns-1))
+ hashes[ns] = h
+ end
n = n + 1
if n > 9 then
report_macros("number of arguments > 9, ignoring %s",s)
- elseif s == "discard" then
- top[s] = ""
- return h .. "0"
else
local m = h .. n
top[s] = m
@@ -96,7 +133,6 @@ local function set(s)
end
end
end
-end
local function get(s)
if s == "ignore" or s == "discard" then
@@ -262,7 +298,7 @@ end
function macros.convertfile(oldname,newname) -- beware, no testing on oldname == newname
local data = loadtexfile(oldname)
- data = interfaces.preprocessed(data) or "" -- interfaces not yet defined
+ data = macros.preprocessed(data) or "" -- interfaces not yet defined
savedata(newname,data)
end
diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua
index cb947f318..cce6ab73b 100644
--- a/tex/context/base/mkiv/luat-run.lua
+++ b/tex/context/base/mkiv/luat-run.lua
@@ -293,6 +293,32 @@ end)
-- end
-- end)
+local report = logs.reporter("csname overload")
+local reported = { }
+
+callback.register("handle_overload", function(fatal,overload,csname,flags)
+ if not reported[csname] then
+ logs.newline()
+ local readstate = status.readstate
+ local filename = readstate.filename
+ local linenumber = readstate.linenumber
+ if filename and linenumber then
+ report("%s, protection level %i, control sequence %a, properties '% t', file %a, line %i",
+ fatal and "fatal error" or "warning",overload,csname,tokens.flags(csname),filename,linenumber)
+ else
+ report("%s, protection level %i, control sequence %a, properties '% t'",
+ fatal and "fatal error" or "warning",overload,csname,tokens.flags(csname))
+ end
+ reported[csname] = true
+ logs.newline()
+ if fatal then
+ cleanup_run()
+ osexit(1)
+ end
+ end
+end)
+
+-- bonus
if environment.initex then
diff --git a/tex/context/base/mkiv/luat-usr.mkiv b/tex/context/base/mkiv/luat-usr.mkiv
index f3868ccf4..ebd96e031 100644
--- a/tex/context/base/mkiv/luat-usr.mkiv
+++ b/tex/context/base/mkiv/luat-usr.mkiv
@@ -38,13 +38,14 @@
%D \macros
%D {definenamedlua}
%D
-%D We provide an interface for defining instances:
+%D We provide an interface for defining instances. We don't have the definers yet
+%D so we do itlow level:
\def\s!lua {lua}
\def\s!code {code}
\def\s!data {data}
-%def\s!start{start}
-%def\s!stop {stop}
+\def\s!start{start}
+\def\s!stop {stop}
%D Beware: because \type {\expanded} is een convert command, the error
%D message will show \type{<inserted text>} as part of the message.
diff --git a/tex/context/base/mkiv/lxml-ini.mkxl b/tex/context/base/mkiv/lxml-ini.mkxl
new file mode 100644
index 000000000..01e2024bf
--- /dev/null
+++ b/tex/context/base/mkiv/lxml-ini.mkxl
@@ -0,0 +1,544 @@
+%D \module
+%D [ file=lxml-ini,
+%D version=2007.08.17,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Todo: auto apply setups (manage at lua end)
+%D Todo: manuak: \xmlinclusion \xmlinclusions
+
+\writestatus{loading}{ConTeXt XML Support / Initialization}
+
+%registerctxluafile{lxml-tab}{} % loader
+%registerctxluafile{lxml-lpt}{} % parser
+%registerctxluafile{lxml-xml}{} % xml finalizers
+%registerctxluafile{lxml-aux}{} % extras using parser
+%registerctxluafile{lxml-mis}{} % extras independent of parser
+\registerctxluafile{lxml-ent}{} % entity hacks
+\registerctxluafile{lxml-tex}{} % tex finalizers
+\registerctxluafile{lxml-dir}{} % ctx hacks
+\registerctxluafile{lxml-ini}{} % interface
+
+\unprotect
+
+% todo: { } mandate so that we can alias
+
+% undocumented:
+
+\def\ctxlxml #1{\ctxlua{lxml.#1}}
+
+% for now indirect .. this will change when we have updated luatex (scan_argument)
+
+\permanent\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}}
+\permanent\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}}
+
+%D Maybe I should add \type {\protected} here:
+
+\permanent\def\xmlloadfile #1#2{\clf_xmlloadfile {#1}{#2}{\directxmlparameter\c!compress}}
+\permanent\def\xmlloadbuffer#1#2{\clf_xmlloadbuffer{#1}{#2}{\directxmlparameter\c!compress}}
+\permanent\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}}
+
+\aliased\let\xmlload\xmlloadfile
+
+% aliased
+
+%let\xmlall \clf_xmlall
+%let\xmlatt \clf_xmlatt
+%let\xmlattdef \clf_xmlattdef
+%let\xmlattribute \clf_xmlattribute
+%let\xmlattributedef \clf_xmlattributedef
+%let\xmlbadinclusions \clf_xmlbadinclusions
+%let\xmlchainatt \clf_xmlchainatt
+%let\xmlchainattdef \clf_xmlchainattdef
+%let\xmlchecknamespace \clf_xmlchecknamespace
+%let\xmlcommand \clf_xmlcommand
+%let\xmlcontext \clf_xmlcontext
+%let\xmlcount \clf_xmlcount
+%let\xmldelete \clf_xmldelete
+%let\xmldirect \clf_xmldirect % in loops, not dt but root
+%let\xmldirectives \clf_xmldirectives
+%let\xmldirectivesafter \clf_xmldirectivesafter
+%let\xmldirectivesbefore \clf_xmldirectivesbefore
+%let\xmldisplayverbatim \clf_xmldisplayverbatim
+%let\xmlelement \clf_xmlelement
+%let\xmlfilter \clf_xmlfilter
+%let\xmlfilterlist \clf_xmlfilterlist
+%let\xmlfirst \clf_xmlfirst
+%let\xmlflush \clf_xmlflush
+%let\xmlflushcontext \clf_xmlflushcontext
+%let\xmlflushlinewise \clf_xmlflushlinewise
+%let\xmlflushpure \clf_xmlflushpure
+%let\xmlflushspacewise \clf_xmlflushspacewise
+%let\xmlflushtext \clf_xmlflushtext
+%let\xmlfunction \clf_xmlfunction
+%let\xmlinclude \clf_xmlinclude
+%let\xmlincludeoptions \clf_xmlincludeoptions
+%let\xmlinclusion \clf_xmlinclusion
+%let\xmlinclusionbase \clf_xmlinclusionbase
+%let\xmlinclusions \clf_xmlinclusions
+%let\xmlindex \clf_xmlindex
+%let\xmlinlineverbatim \clf_xmlinlineverbatim
+%let\xmllast \clf_xmllast
+%let\xmllastatt \clf_xmllastatt
+%let\xmllastmatch \clf_xmllastmatch
+%let\xmllastpar \clf_xmllastpar
+%let\xmlloaddirectives \clf_xmlloaddirectives
+%let\xmlmain \clf_xmlmain
+%let\xmlmatch \clf_xmlmatch
+%let\xmlname \clf_xmlname
+%let\xmlnamespace \clf_xmlnamespace
+%let\xmlnonspace \clf_xmlnonspace
+%let\xmlpar \clf_xmlpar
+%let\xmlparam \clf_xmlparam
+%let\xmlpath \clf_xmlpath
+%let\xmlpopmatch \clf_xmlpopmatch
+%let\xmlpos \clf_xmlpos
+%let\xmlpure \clf_xmlpure
+%let\xmlpushmatch \clf_xmlpushmatch
+%let\xmlraw \clf_xmlraw
+%let\xmlrefatt \clf_xmlrefatt
+%let\xmlregisterns \clf_xmlregisterns % document
+%let\xmlremapname \clf_xmlremapname % element
+%let\xmlremapnamespace \clf_xmlremapnamespace % document
+%let\xmlsave \clf_xmlsave
+%let\xmlsetatt \clf_xmlsetatt
+%let\xmlsetattribute \clf_xmlsetattribute
+%let\xmlsetpar \clf_xmlsetpar
+%let\xmlsetparam \clf_xmlsetparam
+%let\xmlsetsetup \clf_xmlsetsetup
+%let\xmlsnippet \clf_xmlsnippet
+%let\xmlstrip \clf_xmlstrip
+%let\xmlstripanywhere \clf_xmlstripanywhere
+%let\xmlstripnolines \clf_xmlstripnolines
+%let\xmlstripped \clf_xmlstripped
+%let\xmlstrippednolines \clf_xmlstrippednolines
+%let\xmltag \clf_xmltag
+%let\xmltext \clf_xmltext
+%let\xmltobuffer \clf_xmltobuffer % id pattern name
+%let\xmltobuffertextonly \clf_xmltobuffertextonly % id pattern name
+%let\xmltobufferverbose \clf_xmltobufferverbose % id pattern name
+%let\xmltofile \clf_xmltofile % id pattern filename
+%let\xmltoparameters \clf_xmltoparameters
+%let\xmlverbatim \clf_xmlverbatim
+
+\let\xmlposition \xmlindex
+
+\permanent\protected\def\xmlinfo#1{\hbox{\ttxx[\xmlname{#1}]}}
+\permanent\protected\def\xmlshow#1{\startpacked\ttx\xmlverbatim{#1}\stoppacked}
+
+% the next one is handy for mode runs because it enforces a consistent
+% #1 indexing (needed when using \xmltext{main:123}{...} like calls
+
+%let\xmladdindex \clf_xmladdindex
+
+% we need to pass the last argument as function, so
+
+\protected\def\xmlsetfunction#1#2#3{\ctxcommand{xmlsetfunction("#1",\!!bs#2\!!es,#3)}}
+
+% goodie:
+
+\immutable\def\xmltempbuffername{xml-temp}
+
+\permanent\protected\def\prettyprintbuffer#1#2% only used here
+ {\ifdefined\scitebuffer
+ \scitebuffer[#2][#1]%
+ \else
+ \typebuffer[#1][\c!option=#2]%
+ \fi}
+
+\permanent\protected\def\xmlprettyprint#1#2%
+ {\xmltobufferverbose{#1}{.}{\xmltempbuffername}%
+ \prettyprintbuffer\xmltempbuffername{#2}}
+
+\permanent\protected\def\xmlprettyprinttext#1#2%
+ {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}%
+ \prettyprintbuffer\xmltempbuffername{#2}}
+
+\permanent\protected\def\inlineprettyprintbuffer#1#2% only used here
+ {\ifdefined\sciteinlinebuffer
+ \sciteinlinebuffer[#2][#1]%
+ \else
+ \typeinlinebuffer[#1][\c!option=#2]%
+ \fi}
+
+\permanent\protected\def\xmlinlineprettyprint#1#2%
+ {\xmltobufferverbose{#1}{.}{\xmltempbuffername}%
+ \inlineprettyprintbuffer\xmltempbuffername{#2}}
+
+\permanent\protected\def\xmlinlineprettyprinttext#1#2%
+ {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}%
+ \inlineprettyprintbuffer\xmltempbuffername{#2}}
+
+% kind of special:
+
+\aliased\let\xmlstartraw\clf_xmlstartraw
+\aliased\let\xmlstopraw \clf_xmlstopraw
+
+\aliased\let\startxmlraw\clf_xmlstartraw
+\aliased\let\stopxmlraw \clf_xmlstopraw
+
+% these are expandable! todo: \xmldoifelseattribute
+
+%let\xmldoif \clf_xmldoif
+%let\xmldoifnot \clf_xmldoifnot
+%let\xmldoifelse \clf_xmldoifelse
+%let\xmldoiftext \clf_xmldoiftext
+%let\xmldoifnottext \clf_xmldoifnottext
+%let\xmldoifelsetext \clf_xmldoifelsetext
+
+%let\xmldoifatt \clf_xmldoifatt
+%let\xmldoifnotatt \clf_xmldoifnotatt
+%let\xmldoifelseatt \clf_xmldoifelseatt
+
+%let\xmldoifempty \clf_xmldoifempty
+%let\xmldoifnotempty \clf_xmldoifnotempty
+%let\xmldoifelseempty \clf_xmldoifelseempty
+%let\xmldoifselfempty \clf_xmldoifselfempty
+%let\xmldoifnotselfempty \clf_xmldoifnotselfempty
+%let\xmldoifelseselfempty \clf_xmldoifelseselfempty
+
+\aliased\let\xmldoiftextelse \xmldoifelsetext
+\aliased\let\xmldoifemptyelse \xmldoifelseempty
+\aliased\let\xmldoifselfemptyelse \xmldoifelseselfempty
+
+% \startxmlsetups xml:include
+% \xmlinclude{main}{include}{filename|href}
+% \stopxmlsetups
+%
+% \xmlprependsetup{xml:include}
+
+% \let\xmlgrab\xmlsetsetup % obsolete
+% \let\xmlself\s!unknown % obsolete
+
+\aliased\let\xmlsetup\setupwithargumentswapped
+\aliased\let\xmls \setupwithargumentswapped % hardly any faster
+\aliased\let\xmlw \setupwithargument % hardly any faster
+
+% todo: 1:xml:whatever always before 3:xml:something
+
+\permanent\protected\def\xmlprependsetup #1{\clf_xmlprependsetup{*}{#1}}
+\permanent\protected\def\xmlappendsetup #1{\clf_xmlappendsetup {*}{#1}}
+\permanent\protected\def\xmlbeforesetup #1#2{\clf_xmlbeforesetup {*}{#1}{#2}}
+\permanent\protected\def\xmlaftersetup #1#2{\clf_xmlaftersetup {*}{#1}{#2}}
+\permanent\protected\def\xmlremovesetup #1{\clf_xmlremovesetup {*}{#1}}
+\permanent\protected\def\xmlresetsetups {\clf_xmlresetsetups {*}}
+
+\permanent\protected\def\xmlprependdocumentsetup #1#2{\clf_xmlprependsetup{#1}{#2}}
+\permanent\protected\def\xmlappenddocumentsetup #1#2{\clf_xmlappendsetup {#1}{#2}}
+\permanent\protected\def\xmlbeforedocumentsetup #1#2#3{\clf_xmlbeforesetup {#1}{#2}{#3}}
+\permanent\protected\def\xmlafterdocumentsetup #1#2#3{\clf_xmlaftersetup {#1}{#2}{#3}}
+\permanent\protected\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}}
+\permanent\protected\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}}
+
+\permanent\protected\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply *
+\permanent\protected\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2
+
+\aliased\let\xmlregistersetup \xmlappendsetup
+\aliased\let\xmlregisterdocumentsetup\xmlappenddocumentsetup
+
+\def\xmldocument{main}
+
+\permanent\protected\def\xmlregisteredsetups
+ {\xmlstarttiming
+ \xmlflushsetups\xmldocument
+ \xmldefaulttotext\xmldocument % after include
+ \xmlstoptiming}
+
+\permanent\protected\def\xmlregistereddocumentsetups#1#2% id setups
+ {\xmlstarttiming
+ % todo: test for duplicates !
+ \xmlflushdocumentsetups{#1}{#2}%
+ \xmldefaulttotext{#1}% after include
+ \xmlstoptiming}
+
+\permanent\protected\def\xmlstarttiming{\clf_xmlstarttiming} % undocumented
+\permanent\protected\def\xmlstoptiming {\clf_xmlstoptiming} % undocumented
+
+\def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup
+ {\begingroup
+ \edef\xmldocument{#3}% #2 can be \xmldocument and set as such
+ %xmlpushdocument{#3}%
+ #2{#3}{#4}%
+ \setcatcodetable\notcatcodes
+ \doifelsenothing{#5}%
+ {\xmlsetup{#3}{xml:process}}%
+ {\xmlsetup{#3}{#5}}%
+ %xmlpopdocument
+ \endgroup}
+
+\permanent\protected\def\xmlprocessfile {\lxml_process\plusone \xmlload}
+\permanent\protected\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata}
+\permanent\protected\def\xmlprocessbuffer{\lxml_process\zerocount\xmlloadbuffer}
+\aliased \let\xmlprocess \xmlprocessfile
+
+\startxmlsetups xml:flush
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:process
+ \xmlregistereddocumentsetups{#1}{#1}
+ \xmlmain{#1}
+\stopxmlsetups
+
+\permanent\protected\def\xmlloadonly#1#2#3%
+ {\xmlload{#1}{#2}%
+ \xmlregistereddocumentsetups{#1}{#3}}
+
+% replaced by concat
+%
+% \protected\def\xmlconnect#1#2#3% inefficient
+% {\scratchcounter\xmlcount{#1}{#2}\relax
+% \ifcase\scratchcounter \or
+% \xmlall{#1}{#2}%
+% \else
+% \dorecurse \scratchcounter
+% {\ifnum\recurselevel>\plusone#3\fi
+% \xmlidx{#1}{#2}\recurselevel}%
+% \fi}
+
+\permanent\protected\def\xmlcdataobeyedline {\obeyedline}
+\permanent\protected\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\permanent\protected\def\xmlcdatabefore {\begingroup\tt}
+\permanent\protected\def\xmlcdataafter {\endgroup}
+
+% verbatim (dodo:pre/post whitespace, maybe splot verbatim and
+% cdata commands), experimental:
+%
+% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim}
+% \xmlsetfunction{main}{verb} {lxml.inlineverbatim}
+
+% we use an xml: namespace so one has to define a suitable verbatim, say
+%
+% \definetyping[xml:verbatim][typing]
+%
+% this is experimental!
+
+\permanent\tolerant\protected\def\startxmldisplayverbatim[#1]%
+ {\startpacked
+ \edef\currenttyping{#1}%
+ \ifx\currenttyping\empty
+ \let\currenttyping\v!typing
+ \else % maybe test for existence
+ \edef\currenttyping{xml:\currenttyping}%
+ \fi
+ \protected\def\stopxmldisplayverbatim
+ {\endofverbatimlines
+ \stoppacked}%
+ \doinitializeverbatim
+ \beginofverbatimlines}
+
+\let\stopxmldisplayverbatim\relax
+
+\permanent\tolerant\protected\def\startxmlinlineverbatim[#1]%
+ {\begingroup
+ \edef\currenttype{#1}%
+ \ifx\currenttype\empty
+ \let\currenttype\v!type
+ \else % maybe test for existence
+ \edef\currenttype{xml:\currenttype}%
+ \fi
+ \let\stopxmlinlineverbatim\endgroup
+ \doinitializeverbatim}
+
+\let\stopxmlinlineverbatim\relax
+
+% processing instructions
+
+\permanent\protected\def\xmlinstalldirective#1#2%
+ {\clf_xmlinstalldirective{#1}{\csstring#2}}
+
+% an example:
+
+% <?context-tex-directive bgroup ?>
+
+\appendtoks
+ \xmlinstalldirective{tex}{xmltexcommand}%
+\to \everyjob
+
+\permanent\def\xmltexcommand#1{\begincsname#1\endcsname}
+
+% \def\xmlcontextdirective#1% kind class key value
+% {\executeifdefined{xml#1directive}\gobblethreearguments}
+
+% setting up xml:
+%
+% \setupxml[\c!default=] % mkiv only == text
+% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden
+% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text
+
+% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}}
+
+\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden
+
+\installcorenamespace{xml}
+\installcorenamespace{xmldefaults}
+\installcorenamespace{xmlmapvalue}
+
+\installdirectcommandhandler \??xml {xml}
+
+\letvalue{\??xmldefaults\v!normal}\zerocount
+\letvalue{\??xmldefaults\v!none }\zerocount
+\letvalue{\??xmldefaults\v!text }\plusone
+\letvalue{\??xmldefaults\v!hidden}\plustwo
+
+\permanent\protected\def\xmldefaulttotext
+ {\ifcase\xmlprocessingmode
+ \expandafter\gobbleoneargument % 0 (none)
+ \or
+ \expandafter\clf_xmlsetcommandtotext % 1 (normal)
+ \or
+ \expandafter\clf_xmlsetcommandtonone % 2 (hidden)
+ \else
+ \expandafter\gobbleoneargument % (none)
+ \fi}
+
+\appendtoks
+ \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone
+\to \everysetupxml
+
+\setupxml
+ [\c!default=, % flush all
+ \c!compress=\v!no, % strip comment
+ \c!entities=\v!no] % load big entity file
+
+\appendtoks
+ \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities
+\to \everysetupxml
+
+\permanent\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces
+\permanent\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+
+\permanent\def\xmlvalue#1#2% #3
+ {\ifcsname\??xmlmapvalue#1:#2\endcsname
+ \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\permanent\def\xmlmappedvalue#1#2#3%
+ {\ifcsname\??xmlmapvalue#1:#2\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \csname\??xmlmapvalue#1:#3\expandafter\endcsname
+ \fi}
+
+\aliased\let\xmldoifvalueelse\xmldoifelsevalue
+
+\aliased\let\xmlmapval\xmlmapvalue
+\aliased\let\xmlval \xmlvalue
+
+%D Experimental:
+
+\permanent\def\xmlgetindex #1{\clf_xmlgetindex {\xmldocument}{#1}}
+\permanent\def\xmlwithindex #1#2{\clf_xmlwithindex{\xmldocument}{#1}{#2}}
+\permanent\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}}
+
+%D Entities:
+%D
+%D \starttyping
+%D \xmlsetentity{tex}{\TEX{}} % {} needed
+%D \stoptyping
+
+\permanent\protected\def\xmlsetentity#1#2{\clf_xmlsetentity{#1}{\detokenize{#2}}}
+\permanent\protected\def\xmltexentity#1#2{\clf_xmltexentity{#1}{\detokenize{#2}}}
+
+%D The following might change (or even disappear) so we keep it undocumented.
+
+\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower
+
+\permanent\protected\def\xmle
+ {\ifcase\xmlautoentities
+ \expandafter\lxml_e_none
+ \or
+ \expandafter\lxml_e_upper
+ \or
+ \expandafter\lxml_e_upperlower
+ \else
+ \expandafter\lxml_e_none
+ \fi}
+
+\def\lxml_e_none#1#2% safe
+ {#1}
+
+\def\lxml_e_upper#1#2% can be abbreviation
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \else
+ #1%
+ \fi}
+
+\def\lxml_e_upperlower#1#2% can be anything, so unsafe
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \orelse\ifcsname#1\endcsname
+ \csname#1\expandafter\endcsname
+ \else
+ #1%
+ \fi}
+
+%D We keep these around as there are also MP, LUA and TEX variants but they are not
+%D the same as in \MKII.
+
+\permanent\tolerant\protected\def\processXMLbuffer[#1]{\xmlprocessbuffer{temp}{#1}{}}
+\permanent \protected\def\processXMLfile #1{\xmlprocessfile {temp}{#1}{}}
+\permanent \protected\def\XMLdata #1{\xmlprocessdata {temp}{#1}{}}
+
+\aliased\let\processxmlbuffer\processXMLbuffer
+\aliased\let\processxmlfile \processXMLfile
+\aliased\let\xmldata \XMLdata
+
+\permanent\protected\def\xmlsetinjectors [#1]{\clf_xmlsetinjectors{#1}}
+\permanent\protected\def\xmlresetinjectors {\clf_xmlresetinjectors{}}
+
+% \def\xmlinjector#1{\executeifdefined{#1}\donothing}
+
+\permanent\def\xmlinjector#1{\fastsetup{xml:directive:injector:#1}}
+
+\startsetups xml:directive:injector:page
+ \page
+\stopsetups
+
+\startsetups xml:directive:injector:column
+ \column
+\stopsetups
+
+\startsetups xml:directive:injector:blank
+ \blank
+\stopsetups
+
+\startsetups xml:directive:injector:noline
+ \vskip-\lineheight
+\stopsetups
+
+\aliased\let\xmlapplyselectors\clf_xmlapplyselectors
+
+% \let\xmlcatcodes\notcatcodes
+
+\protect \endinput
+
+% \newcount\charactersactiveoffset \charactersactiveoffset="10000
+%
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \startextendcatcodetable\xmlcatcodes % not needed
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \ctxlua { % entities are remembered in the format
+% commands.remapentity("<",characters.activeoffset + utf.byte("<"))
+% commands.remapentity("&",characters.activeoffset + utf.byte("&"))
+% commands.remapentity(">",characters.activeoffset + utf.byte(">"))
+% }
diff --git a/tex/context/base/mkiv/math-ali.mkxl b/tex/context/base/mkiv/math-ali.mkxl
new file mode 100644
index 000000000..997ecd3d7
--- /dev/null
+++ b/tex/context/base/mkiv/math-ali.mkxl
@@ -0,0 +1,1893 @@
+%D \module
+%D [ file=math-ali,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Math Alignments,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Math Alignments}
+
+\unprotect
+
+%D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code
+%D is not gathered in files with the same name. In the meantime this code has been
+%D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the
+%D fact that alignments are tricky with rspect to tagging.
+
+% export:
+%
+% alignment : ok
+% cases :
+% matrix : ok
+% substack :
+
+%D \macros
+%D {definemathalignment, setupmathalignment, startmathalignment}
+%D
+%D Modules may provide additional alignment features. The following mechanisms are
+%D provided by the core.
+
+\newtoks\t_math_align_a
+\newtoks\t_math_align_b
+\newtoks\t_math_align_c
+
+\newskip\d_math_eqalign_distance
+
+\protected\def\math_eqalign_distance
+ {\relax
+ \ifdim\d_math_eqalign_distance>\zeropoint
+ % \hskip\d_math_eqalign_distance
+ \tabskip\d_math_eqalign_distance
+ \fi
+ \mathalignmentparameter\c!separator
+ \relax}
+
+\def\displayopenupvalue{.25\bodyfontsize}
+
+\def\math_build_eqalign
+ {\scratchtoks\emptytoks
+ \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax
+ \scratchcounterone\mathalignmentparameter\c!m
+ \scratchcountertwo\mathalignmentparameter\c!n
+ \etoksapp\scratchtoks{\the\t_math_align_a}%
+ \scratchcounter\plusone
+ \dorecurse{\numexpr\scratchcounterone*\scratchcountertwo-\plusone\relax}
+ {\ifnum\scratchcounter=\scratchcountertwo
+ \scratchcounter\plusone
+ \etoksapp\scratchtoks{\math_eqalign_distance}%
+ \else
+ \advance\scratchcounter\plusone
+ \fi
+ \etoksapp\scratchtoks{\the\t_math_align_b}}%
+ \etoksapp\scratchtoks{\the\t_math_align_c}}
+
+\def\math_math_in_eqalign#1%
+ {\startforceddisplaymath
+ \tabskip\zeropoint
+ \everycr\emptytoks
+ {{}#1{}}%
+ \stopforceddisplaymath}
+
+\def\math_text_in_eqalign#1%
+ {\startimath
+ \tabskip\zeropoint
+ \everycr\emptytoks
+ #1%
+ \stopimath}
+
+\def\eqalign#1% why no halign here, probably because of displaywidth
+ {\emptyhbox
+ \mskip\thinmuskip
+ \vcenter
+ {\math_openup\displayopenupvalue % was: \openup\jot
+ \mathsurround\zeropoint
+ \ialign{%
+ \strut
+ \hfil
+ \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath
+ \aligntab
+ \startforceddisplaymath{{}\alignmark\alignmark{}}\stopforceddisplaymath
+ \hfil\crcr
+ #1\crcr}%
+ }%
+ \mskip\thinmuskip}
+
+% preamble is scanned for tabskips so we need the span to prevent an error message
+
+\setnewconstant\eqalignmode\plusone
+
+% use zeroskipplusfill
+
+\def\math_prepare_r_eqalign_no
+ {\t_math_align_a
+ {\strut
+ \tabskip\zeropoint
+ \alignmark\alignmark % for picking up the number
+ \aligntab
+ \math_first_in_eqalign
+ \hfil
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \t_math_align_b
+ {\aligntab
+ \math_next_in_eqalign
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \t_math_align_c
+ {\hfil
+ \aligntab
+ \span
+ \math_text_in_eqalign{\alignmark\alignmark}%
+ \tabskip\zeropoint}%
+ \orelse\ifnum\mathraggedstatus=\plusthree
+ \t_math_align_c
+ {\hfil
+ \tabskip\zeropoint\s!plus 1\s!fill
+ \aligntab
+ \span
+ \math_text_in_eqalign{\alignmark\alignmark}%
+ \tabskip\zeropoint}%
+ \else
+ \t_math_align_c
+ {\hfil
+ \tabskip\centering
+ \aligntab
+ \span
+ \llap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \tabskip\zeropoint}%
+ \fi
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
+ \tabskip\centering}
+
+\def\math_prepare_l_eqalign_no % \checkeddisplaymath
+ {\t_math_align_a
+ {\strut
+ \tabskip\zeropoint
+ \alignmark\alignmark % for picking up the number
+ \aligntab
+ \math_first_in_eqalign
+ \hfil
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \t_math_align_b
+ {\aligntab
+ \math_next_in_eqalign
+ \math_left_of_eqalign
+ \span
+ \math_math_in_eqalign{\alignmark\alignmark}%
+ \math_right_of_eqalign
+ \tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \t_math_align_c
+ {\hfil
+ \aligntab
+ \kern-\displaywidth
+ \span
+ \rlap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \tabskip\displaywidth}%
+ \orelse\ifnum\mathraggedstatus=\plusthree
+ \t_math_align_c
+ {\hfil
+ \tabskip\zeropoint\s!plus 1\s!fill
+ \aligntab
+ \kern-\displaywidth
+ \span
+ \math_rlap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \tabskip\displaywidth}%
+ \else
+ \t_math_align_c
+ {\hfil
+ \tabskip\centering
+ \aligntab
+ \kern-\displaywidth
+ \span
+ \rlap{\math_text_in_eqalign{\alignmark\alignmark}}%
+ \tabskip\displaywidth}%
+ \fi
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
+ \tabskip\centering}
+
+\def\math_halign_checked
+ {\halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi}
+
+\def\math_both_eqalign_no_normal#1#2%
+ {\ifmmode
+ \the\mathdisplayaligntweaks
+ \vcenter\bgroup
+ \enforced\let\math_finish_eqalign_no\egroup
+ \else
+ \enforced\let\math_finish_eqalign_no\relax
+ \fi
+ #1%
+ \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr#2\crcr\egroup
+ \math_finish_eqalign_no}
+
+\installcorenamespace {mathalignlocation}
+
+\setvalue{\??mathalignlocation\v!top }{\let\math_alignment_halign_method\halign\tpack}
+\setvalue{\??mathalignlocation\v!bottom}{\let\math_alignment_halign_method\halign\vpack}
+\setvalue{\??mathalignlocation\v!center}{\let\math_alignment_halign_method\halign\vcenter}
+
+\def\math_both_eqalign_no_aligned#1%
+ {\let\math_alignment_halign_method\math_halign_checked
+ \ifmmode
+ \the\mathdisplayaligntweaks
+ \global\mathnumberstatus\plusone
+ \ifcase\mathraggedstatus
+ \def\math_finish_eqalign_no{\crcr\egroup}%
+ \else % we're in a mathbox
+ \ifcsname\??mathalignlocation\mathalignmentparameter\c!location\endcsname
+ \lastnamedcs % top|bottom|center as suggested by HM
+ \else
+ \vcenter
+ \fi
+ \bgroup
+ \def\math_finish_eqalign_no{\crcr\egroup\egroup}%
+ \fi
+ \fi
+ #1%
+ \math_alignment_halign_method\expandafter\bgroup\the\scratchtoks\crcr}
+
+\def\math_rlap#1%
+ {\setbox\scratchbox\hbox{#1}%
+ \ifdim\wd\scratchbox>\d_math_number_correction
+ \global\d_math_number_correction\wd\scratchbox
+ \fi
+ \box\scratchbox
+ \global\mathnumberstatus\plustwo}
+
+\def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no}
+\def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no}
+\def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no}
+\def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no}
+\def\math_finish_eqalign_no {\crcr\egroup}
+
+\let\reqalignno\relax
+\let\leqalignno\relax
+\let\eqalignno \relax
+
+%D Here we implement the user interface part. We start with basic math alignments:
+
+\newcount \c_math_eqalign_column
+\newconditional\c_math_eqalign_first
+
+\newtoks \everymathalignment
+\newtoks \everymathalignmentdone
+
+\permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]%
+ {\aligntab
+ \strc_formulas_place_number_nested{#1}{#2}}
+
+\permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]%
+ {\aligntab
+ \dostoptagged % finish cell
+ \strc_formulas_place_number_nested{#1}{#2}%
+ \math_number_right_of_eqalign
+ \global\settrue\c_math_eqalign_first
+ \crcr
+ \dostoptagged} % finish row
+
+\permanent\protected\def\math_alignment_NC
+ {\relax
+ \ifconditional\c_math_eqalign_first
+ \ifx\p_math_alignment_number\v!auto
+ \strc_formulas_place_number_nested{+}{}%
+ \fi
+ \global\setfalse\c_math_eqalign_first
+ \fi
+ \math_number_left_of_eqalign
+ \aligntab}
+
+\permanent\protected\def\math_alignment_EQ
+ {\NC=}
+
+\installmacrostack\NC % maybe more to shared table definitions
+\installmacrostack\NN % maybe more to shared table definitions
+\installmacrostack\EQ % maybe more to shared table definitions
+\installmacrostack\NR % maybe more to shared table definitions
+\installmacrostack\BC % maybe more to shared table definitions
+\installmacrostack\EC % maybe more to shared table definitions
+
+\appendtoks
+ \push_macro_NC
+ \push_macro_NN
+ \push_macro_EQ
+ \push_macro_NR
+ \enforced\let\NC\math_alignment_NC
+ \enforced\let\NN\math_alignment_NN
+ \enforced\let\EQ\math_alignment_EQ
+ \enforced\let\NR\math_alignment_NR
+ \global\settrue\c_math_eqalign_first
+\to \everymathalignment
+
+\appendtoks
+ \pop_macro_NR
+ \pop_macro_EQ
+ \pop_macro_NN
+ \pop_macro_NC
+\to \everymathalignmentdone
+
+\let\math_alignment_snap_start\relax
+\let\math_alignment_snap_stop \relax
+
+% % experimental:
+%
+% \def\math_alignment_snap_start
+% {\ifgridsnapping
+% \edef\p_math_alignment_grid{\mathalignmentparameter\c!grid}%
+% \ifx\p_math_alignment_grid\v!no\else
+% \snaptogrid[\p_math_alignment_grid]\vbox\bgroup
+% \fi
+% \fi}
+%
+% \def\math_alignment_snap_stop
+% {\ifgridsnapping
+% \ifx\p_math_alignment_grid\v!no\else
+% \egroup
+% \fi
+% \fi}
+%
+% % doesn't work well, so:
+
+\let\math_alignment_snap_start\relax
+\let\math_alignment_snap_stop \relax
+
+% end of experimental
+
+\newconditional\c_math_alignment_auto_number
+
+% \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex
+
+\permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]%
+ {\edef\currentmathalignment{#1}%
+ \ifarguments\or\or
+ \setupmathalignment[#1][#2]% bad! ungrouped
+ \fi
+ \math_alignment_snap_start
+ \the\everymathalignment
+ \c_math_eqalign_column\zerocount
+ \edef\p_math_alignment_number{\mathalignmentparameter\c!number}%
+ \processcommacommand
+ [\mathalignmentparameter\c!align]%
+ {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument
+ \global\c_math_eqalign_column\plusone
+ \dostarttagged\t!math\empty
+ \dostarttagged\t!mathtable\currentmathalignment
+ \numberedeqalign}
+
+\def\math_alignment_stop
+ {\math_finish_eqalign_no
+ \dostoptagged
+ \dostoptagged
+ \the\everymathalignmentdone
+ \math_alignment_snap_stop}
+
+\installcorenamespace{mathalignment}
+\installcorenamespace{mathalignmentvariant}
+
+\installcommandhandler \??mathalignment {mathalignment} \??mathalignment
+
+\appendtoks
+ \setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}%
+ \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}%
+\to \everydefinemathalignment
+
+\setupmathalignment
+ [\c!n=2,
+ \c!m=1,
+ \c!distance=\emwidth,
+ \c!grid=\v!math]
+
+\definemathalignment[align] % default case (this is what amstex users expect)
+\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
+
+% special case.. in case one mistypes ..
+
+\ifdefined \startalignment
+
+ \let\align_math_normal_start\startalign
+ \let\align_math_normal_stop \stopalign
+
+ \let\align_text_normal_start\startalignment
+ \let\align_text_normal_stop \stopalignment
+
+ \permanent\overloaded\protected\def\startalign
+ {\ifmmode
+ \enforced\let\stopalign\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align
+ \expandafter\align_math_normal_start
+ \orelse\ifinformula
+ \enforced\let\stopalign\align_math_normal_stop
+ \expandafter\align_math_normal_start
+ \else
+ \enforced\let\stopalign\align_text_normal_stop
+ \expandafter\align_text_normal_start
+ \fi}
+
+ \overloaded\let\stopalign\relax
+
+ \permanent\overloaded\protected\def\startalignment
+ {\ifmmode
+ \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align
+ \expandafter\align_math_normal_start
+ \orelse\ifinformula
+ \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align
+ \expandafter\align_math_normal_start
+ \else
+ \enforced\let\stopalignment\align_text_normal_stop
+ \expandafter\align_text_normal_start
+ \fi}
+
+ \overloaded\let\stopalignment\relax
+
+\fi
+
+%
+
+\permanent\protected\def\numberedeqalign
+ {\doifelse{\formulaparameter\c!location}\v!left
+ \math_handle_eqalign_no_l_aligned
+ \math_handle_eqalign_no_r_aligned}
+
+\def\math_first_in_eqalign
+ {\global\c_math_eqalign_column\plusone
+ \dostarttagged\t!mathtablerow \empty
+ \dostarttagged\t!mathtablecell\empty}
+
+\def\math_next_in_eqalign
+ {\global\advance\c_math_eqalign_column\plusone
+ \dostoptagged % finish cell
+ \dostarttagged\t!mathtablecell\empty}
+
+\def\math_left_of_eqalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi
+ \fi}
+
+\def\math_right_of_eqalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi
+ \fi}
+
+\newconditional\c_math_alignment_local_number % not used but when true puts in front (todo)
+
+\def\math_number_right_of_eqalign
+ {\ifcase\wd\b_strc_formulas_number\else
+ \ifconditional\c_math_alignment_local_number
+ \ifcase\c_strc_math_number_location\or\or
+ \box\b_strc_formulas_number
+ \fi
+ \else
+ \box\b_strc_formulas_number
+ \fi
+ \fi}
+
+\def\math_number_left_of_eqalign
+ {\ifcase\wd\b_strc_formulas_number\else
+ \ifconditional\c_math_alignment_local_number
+ \ifcase\c_strc_math_number_location\or
+ \box\b_strc_formulas_number
+ \fi
+ \fi
+ \fi}
+
+% \def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments)
+% {\expandafter\let\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\endcsname
+% \csname\??mathalignmentvariant\ifcsname\??mathalignmentvariant#1\endcsname#1\else\v!normal\fi\endcsname}
+
+\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments)
+ {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname
+ \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax}
+
+\letvalue{\??mathalignmentvariant\v!normal}\zerocount
+\letvalue{\??mathalignmentvariant\v!left }\plusone
+\letvalue{\??mathalignmentvariant\v!right }\plustwo
+\letvalue{\??mathalignmentvariant\v!middle}\plusthree
+
+\permanent\protected\def\math_align_NR_generic[#1][#2]%
+ {\strc_formulas_place_number_nested{#1}{#2}\crcr}
+
+%D \starttyping
+%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0]
+%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1]
+%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2]
+%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3]
+%D \stoptyping
+
+%D \startbuffer
+%D \placeformula \startformula \eqalignno {
+%D a &= b & \formulanumber \cr
+%D c &= d \cr
+%D &= e \cr
+%D &= f & \formulanumber
+%D } \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR[for:demo-a-1]
+%D \NC \EQ g \NR[for:demo-a-2][a]
+%D \NC \EQ h \NR[for:demo-a-3][b]
+%D \NC \EQ i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR
+%D \NC \EQ g \NR
+%D \NC \EQ h \NR
+%D \NC \EQ i \NR[+]
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \NC \eq b \NR[+]
+%D \NC c \NC \neq d \NR
+%D \NC \NC \neq f \NR[for:demo-b-1]
+%D \NC \NC \geq g \NR[for:demo-b-2][a]
+%D \NC \NC \leq h \NR[for:demo-b-3][b]
+%D \NC \NC \neq i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={left,middle,right}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={right,middle,left}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \setupmathalignment[n=3,align={middle,middle,middle}]%
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \dorecurse{5}{\startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula}
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathcases, setupmathcases, startmathcases}
+%D
+%D Another wish \unknown
+
+\installcorenamespace{mathcases}
+
+\installcommandhandler \??mathcases {mathcases} \??mathcases
+
+\setupmathcases
+ [\c!distance=\emwidth,
+ \c!strut=\v!yes, % new
+ \c!numberdistance=2.5\emwidth,
+ \c!left={\left\{\mskip\thinmuskip},
+ \c!right={\right.}]
+
+\appendtoks
+ \setuevalue{\e!start\currentmathcases}{\math_cases_start[\currentmathcases]}%
+ \setvalue {\e!stop \currentmathcases}{\math_cases_stop}%
+\to \everydefinemathcases
+
+\permanent\protected\def\math_cases_NC_zero
+ {\math_cases_NC}
+
+\permanent\protected\def\math_cases_MC_zero
+ {\math_cases_NC
+ \ifmmode\else
+ \startimath
+ \enforced\let\math_cases_end_math\stopimath
+ \fi}
+
+\let\math_cases_end_math\relax
+
+\permanent\protected\def\math_cases_NR_zero
+ {\unskip
+ \math_cases_end_math
+ \aligntab
+ \global\enforced\let\math_cases_NC\math_cases_NC_first
+ \dodirectdoubleempty\math_cases_NR}
+
+\permanent\protected\def\math_cases_NC_first
+ {\global\enforced\let\math_cases_NC\math_cases_NC_second}
+
+\permanent\protected\def\math_cases_NC_second
+ {\math_cases_end_math\aligntab}
+
+\let\math_cases_NR\math_align_NR_generic
+
+\installmacrostack\math_cases_NC
+
+\permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]%
+ {\begingroup
+ \edef\currentmathcases{#1}%
+ \ifarguments\or\or
+ \setupcurrentmathcases[#2]%
+ \fi
+ \edef\p_strut{\mathcasesparameter\c!strut}%
+ \ifx\p_strut\v!yes
+ \enforced\let\math_cases_strut\strut
+ \else
+ \enforced\let\math_cases_strut\relax
+ \fi
+ \mathcasesparameter\c!left
+ \vcenter\bgroup
+ \push_macro_math_cases_NC
+ \enforced\let\endmath\relax
+ \enforced\let\NC\math_cases_NC_zero
+ \enforced\let\MC\math_cases_MC_zero
+ \enforced\let\NR\math_cases_NR_zero
+ \global\enforced\let\math_cases_NC\math_cases_NC_first
+ \normalbaselines
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \global\c_math_eqalign_column\plusone
+ \halign\bgroup
+ \startimath
+ \mathcasesparameter\c!style
+ \alignmark\alignmark
+ \stopimath
+ \hfil
+ \aligntab
+ \hskip\mathcasesparameter\c!distance\relax
+ \pop_macro_math_cases_NC
+ \math_cases_strut % looks better
+ \alignmark\alignmark
+ \hfil
+ \aligntab
+ \hskip\mathcasesparameter\c!numberdistance\relax
+ \let\formuladistance\!!zeropoint
+ \span\math_text_in_eqalign{\alignmark\alignmark}%
+ \crcr} % todo: number
+
+\def\math_cases_stop
+ {\crcr
+ \egroup
+ \popmacro\math_cases_NC
+ \egroup
+ \mathcasesparameter\c!right
+ \endgroup}
+
+\definemathcases[cases]
+\definemathcases[\v!mathcases]
+
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR[+]
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR[+]
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathmatrix, setupmathmatrix, startmathmatrix}
+%D
+%D Yet another one \unknown. This time we implement the lot a bit
+%D different which is a side effect of getting the tagging right. In
+%D retrospect the main alignment could be done this way but \unknown
+
+\installcorenamespace{mathmatrix}
+
+\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix
+
+\setupmathmatrix
+ [\c!distance=\emwidth,
+ \c!left=,
+ \c!right=,
+ \c!align=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}%
+ \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem
+\to \everydefinemathmatrix
+
+\def\math_matrix_start_table
+ {\global\c_math_eqalign_column\zerocount
+ \dostarttagged\t!math\empty
+ \dostarttagged\t!mathtable\empty}
+
+\def\math_matrix_stop_table
+ {\dostoptagged
+ \dostoptagged}
+
+\def\math_matrix_start_row
+ {\noalign{\global\c_math_eqalign_column\zerocount}%
+ \dostarttagged\t!mathtablerow\empty}
+
+\def\math_matrix_stop_row
+ {\dostoptagged}
+
+\protected\def\math_matrix_start_cell
+ {\dostarttagged\t!mathtablecell\empty
+ \hss
+ \math_left_of_eqalign
+ \startimath
+ \math_matrix_set_style
+ \tabskip\zeropoint
+ \everycr\emptytoks}
+
+\protected\def\math_matrix_stop_cell
+ {\stopimath
+ \math_right_of_eqalign
+ \hss
+ \dostoptagged}
+
+% We could construct a preamble with alignment and such embedded but the number
+% of matrices with many rows is normally so low that it doesn't pay of at all.
+
+\protected\def\math_matrix_distance
+ {\relax
+ \ifdim\d_math_eqalign_distance>\zeropoint
+ \hskip\d_math_eqalign_distance
+ \fi
+ \relax}
+
+\def\math_matrix_preamble
+ {\math_matrix_strut
+ \global\advance\c_math_eqalign_column\plusone
+ \math_matrix_start_cell
+ \alignmark\alignmark
+ \math_matrix_stop_cell
+ \aligntab
+ \aligntab
+ \math_matrix_distance
+ \global\advance\c_math_eqalign_column\plusone
+ \math_matrix_start_cell
+ \alignmark\alignmark
+ \math_matrix_stop_cell}
+
+\newconditional\c_math_matrix_first
+
+\permanent\protected\def\math_matrix_NR
+ {\aligntab\omit
+ \math_matrix_stop_row
+ \math_matrix_pickup
+ \crcr
+ \math_matrix_start_row}
+
+\permanent\protected\def\math_matrix_NC
+ {\ifconditional\c_math_matrix_first
+ \expandafter\math_matrix_NC_yes
+ \else
+ \expandafter\math_matrix_NC_nop
+ \fi}
+
+\permanent\protected\def\math_matrix_pickup{\global\settrue \c_math_matrix_first}
+\permanent\protected\def\math_matrix_NC_yes{\global\setfalse\c_math_matrix_first}
+\permanent\protected\def\math_matrix_NC_nop{\aligntab} % avoids lookahead
+
+% \def\math_matrix_stop_wrapup
+% {\crcr
+% \strut
+% \crcr
+% \noalign{\vskip-\struthtdp}}
+
+\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\endmath\relax
+ %
+ \setbox\nextbox\vbox\bgroup
+ \math_matrix_start_table
+ \halign \bgroup
+ % preamble
+ \span\math_matrix_preamble
+ % done
+ \crcr
+ \math_matrix_start_row}
+
+\def\math_matrix_stop_processing
+ {%\math_matrix_stop_wrapup % optional
+ \math_matrix_stop_row
+ \egroup
+ \math_matrix_stop_table
+ \egroup
+ \mathmatrixleft
+ \math_matrix_finish_nextbox
+ \mathmatrixright
+ \egroup}
+
+\let\math_matrix_strut \strut
+\let\math_matrix_set_style\relax
+
+\def\math_matrix_check_settings
+ {\edef\p_strut{\mathmatrixparameter\c!strut}%
+ \ifx\p_strut\v!no
+ \enforced\let\math_matrix_strut\relax
+ \else
+ \enforced\let\math_matrix_strut\strut
+ \ifx\p_strut\v!yes\else
+ \spacing\p_strut
+ \fi
+ \fi
+ \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax
+ \edef\math_matrix_set_style{\mathmatrixparameter\c!style}}
+
+\def\math_matrix_set_defaults
+ {\normalbaselines % hm, spacing ?
+ \mathsurround\zeropoint
+ \tabskip\zeropoint}
+
+\def\math_matrix_set_columns_step
+ {\advance\c_math_eqalign_column\plusone
+ %\c_math_matrix_columns\c_math_eqalign_column
+ \math_eqalign_set_column}
+
+\def\math_matrix_set_columns
+ {\c_math_eqalign_column\zerocount
+ \rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step}
+
+\newcount\c_math_eqalign_column_saved
+
+% \installglobalmacrostack\c_math_matrix_first
+
+\tolerant\protected\def\math_matrix_start[#1]#*[#2]%
+ {\begingroup
+ \globalpushmacro\c_math_matrix_first % hm, does that work?
+ \c_math_eqalign_column_saved\c_math_eqalign_column
+ \globalpushmacro\c_math_eqalign_first
+ \edef\currentmathmatrix{#1}%
+ \setupcurrentmathmatrix[#2]%
+ \math_matrix_check_settings
+ \math_matrix_set_defaults
+ \math_matrix_set_columns
+ \math_matrix_start_processing}
+
+\def\math_matrix_stop
+ {\math_matrix_stop_processing
+ \globalpushmacro\c_math_eqalign_first
+ \global\c_math_eqalign_column\c_math_eqalign_column_saved
+ \globalpopmacro\c_math_matrix_first
+ \endgroup}
+
+% vcenter:
+%
+% delta = (height(v) + depth(v))/2
+% axis = math_axis_size(cur_size)
+% height(v) = delta + axis
+% depth(v) = delta - axis
+
+\installcorenamespace{mathmatrixalignlocation}
+
+\let\mathmatrixleft \empty % experimental hook
+\let\mathmatrixright\empty % experimental hook
+
+\setvalue{\??mathmatrixalignlocation\v!top }{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax}
+\setvalue{\??mathmatrixalignlocation\v!high }{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax}
+\setvalue{\??mathmatrixalignlocation\v!center}{\relax}
+\setvalue{\??mathmatrixalignlocation\v!lohi} {\relax}
+\setvalue{\??mathmatrixalignlocation\v!normal}{\relax}
+\setvalue{\??mathmatrixalignlocation\v!bottom}{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax}
+\setvalue{\??mathmatrixalignlocation\v!low }{\lower\dimexpr(\nextboxdp-\nextboxht)/2\relax}
+
+\def\math_matrix_finish_nextbox
+ {\begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup
+ \normalstartimath
+ \mathmatrixparameter\c!left
+ \vcenter{\box\nextbox}%
+ \mathmatrixparameter\c!right
+ \normalstopimath
+ \egroup}
+
+\definemathmatrix[matrix]
+\definemathmatrix[\v!mathmatrix]
+
+%D \startbuffer
+%D \placeformula \startformula[-] \startmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25]
+%D
+%D \startbuffer
+%D \placeformula \startformula[-] \startbmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopbmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Taco added some code (dedicated to Aditya Mahajan) that gives more
+%D control over aligments:
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix
+%D \NC a + x \NC = \NC a + d \NR
+%D \NC y \NC = \NC d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [distance=3pt,align={right,left}]
+%D \NC a + x \NC = a + d \NR
+%D \NC y \NC = d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [left=\left(,right=\right)]
+%D \NC a + x \NR
+%D \NC y \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D A bit more complex code:
+%D
+%D \startbuffer
+%D \startformula
+%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}}
+%D \left\{ (R_1, R_2) :
+%D \startmatrix[distance=1em,align={left,left,right}]
+%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR
+%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR
+%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR
+%D \stopmatrix
+%D \right\}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {startmatrices}
+%D
+%D Just a handy keystroke safer:
+
+\permanent\protected\def\startmatrices
+ {\begingroup
+ \setupmathmatrix}
+
+\permanent\protected\def\stopmatrices
+ {\endgroup}
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix[left={\left(},right={\right)}]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=low]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=high]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \startformula
+%D \startmatrices[left={\left(},right={\right)}]
+%D \startmatrix
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=bottom]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=top]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopmatrices
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % does not run well: \getbuffer
+
+%D Handy for the \type {m-matrix} module:
+
+\permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#2]%
+ {\begingroup
+ \edef\currentmathmatrix{#1}%
+ \setupcurrentmathmatrix[#2]%
+ \math_matrix_start[\currentmathmatrix]}
+
+\permanent\protected\def\stopnamedmatrix
+ {\math_matrix_stop
+ \endgroup}
+
+%D The following code is derived from Aditya's simplematrix prototype but
+%D adapted to regular mathmatrices (which saves some code so it can go into
+%D the core):
+
+\def\math_matrix_simple_row#1%
+ {\rawprocesscommalist[#1]\math_matrix_simple_col
+ \toksapp\scratchtoks{\NR}}
+
+\def\math_matrix_simple_col#1%
+ {\toksapp\scratchtoks{\NC#1}}
+
+\permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3%
+ {\begingroup
+ \edef\currentmathmatrix{#1}%
+ \setupcurrentmathmatrix[#2]%
+ \scratchtoks\emptytoks
+ \processlist[];\math_matrix_simple_row[#3]%
+ \math_matrix_start[\currentmathmatrix]%
+ \the\scratchtoks
+ \math_matrix_stop
+ \endgroup}
+
+%D We hook it into the normal mathmatrix code:
+
+\appendtoks
+ \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}%
+ \ifx\p_simplecommand\empty\else
+ \setuevalue{\p_simplecommand}{\math_matrix_simple[\currentmathmatrix]}%
+ \fi
+\to \everydefinemathmatrix
+
+%D And predefine some matrices:
+
+\definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle]
+\definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle]
+\definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle]
+
+\definemathmatrix[thematrix][matrix:parentheses][\c!simplecommand=thematrix]
+
+%D \startbuffer
+%D \startformula
+%D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \startformula
+%D \startthematrix
+%D \NC 1\NC 2\NC 3\NC 4\NR
+%D \NC 5\NC 6\NC 7\NC 8\NR
+%D \NC 9\NC10\NC11\NC12\NR
+%D \stopthematrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {startintertext}
+%D
+%D Preliminary feature:
+%D
+%D {\em example code}
+%D
+%D The intertext commands have to be expandable (in aligment lookahead) so
+%D we cannot use \type {\protected}.
+
+\permanent\def\startintertext#1\stopintertext
+ {\noalign{\math_intertext{#1}}}
+
+\permanent\let\stopintertext\relax
+
+\permanent\def\intertext#1%
+ {\noalign{\math_intertext{#1}}}
+
+\protected\def\math_intertext#1%
+ {\penalty\postdisplaypenalty
+ \afterdisplayspace
+ \vbox{\forgetall\noindent#1\par}%
+ \penalty\predisplaypenalty
+ \beforedisplayspace}
+
+%D \macros
+%D {substack}
+%D
+%D Preliminary code:
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{%
+%D \startsubstack
+%D i = 1 \NR
+%D i \neq n \NR
+%D i \neq m
+%D \stopsubstack
+%D }a_i
+%D \stopformula
+%D \stopbuffer
+%D
+%D \getbuffer which was typed as \typebuffer
+%D
+%D Notice that these macros give the correct spacing for
+%D subscripts. Compare for example
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{\startsubstack a \NR b \NR \stopsubstack}
+%D \text{ and }
+%D \sum_{\scriptstyle a \atop \scriptstyle}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+% no tagging yet : how is it supposed to be coded?
+
+\permanent\protected\def\startsubstack
+ {\begingroup
+ \vcenter\bgroup
+ \baselineskip\mathstacktotal
+ \lineskip\mathstackvgap
+ \lineskiplimit\lineskip
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \enforced\let\NC\relax
+ \enforced\let\MC\relax
+ \enforced\let\NR\crcr
+ \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr}
+
+\permanent\def\stopsubstack % todo: \protected and delayed
+ {\crcr
+ \egroup
+ \egroup
+ \endgroup}
+
+% %D \macros
+% %D {bordermatrix}
+% %D
+% %D In \PLAIN\ \TEX\ the width of a parenthesis is stored in
+% %D the \DIMENSION\ \type{\mathparentwd}. This value is derived from
+% %D the width of \type{\tenrm B}, so let's take care of it now:
+%
+% \ifx\mathparentwd\undefined \newdimen\mathparentwd \fi
+%
+% \let\normalbordermatrix\bordermatrix % move that code to here instead
+%
+% \protected\def\bordermatrix
+% {\begingroup
+% \setbox\scratchbox\hbox{\mr\char"239C}%
+% \global\mathparentwd\wd\scratchbox
+% \endgroup
+% \normalbordermatrix}
+%
+% \def\bordermatrix
+% {\begingroup
+% \mr
+% \global\mathparentwd\fontcharwd\font"239C\relax
+% \endgroup
+% \normalbordermatrix}
+
+%D \macros{overset, underset}
+%D
+%D The macros \type{\overset} and \type{\underset} are provided by
+%D \AMS\ packages in \LATEX. These macro allows you to place a symbol
+%D above or below another symbol, irrespective of whether the other
+%D symbol is a relation or something else, and without influencing the
+%D spacing. For most cases there is a better way to do such things
+%D (declaring a math command with limop option, or using accents), but
+%D occasionally these macros can be useful, for example:
+%D
+%D \startbuffer
+%D \startformula
+%D \overset{*}{X} \underset{*}{X}
+%D \stopformula
+%D \stopbuffer
+%D \typebuffer \getbuffer
+%D
+%D Use these macros sparingly. Remember, \TEX\ was designed for
+%D mathematics, so there is usually a proper method for typesetting
+%D common math notation.
+%D
+%D These macros are a cleaner version of \type {\binrel@} and
+%D \type {\binrel@@} macros in \AMSTEX\ packages.
+
+\def\math_binrel_apply#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\thinmuskip 0mu
+ \medmuskip -1mu
+ \thickmuskip -1mu
+ \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}%
+ \kern-\wd\scratchbox
+ \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}%
+ \ifdim\wd\scratchbox<\zeropoint
+ \endgroup
+ \expandafter\mathbin
+ \orelse\ifdim\wd\scratchbox>\zeropoint
+ \endgroup
+ \doubleexpandafter\mathrel
+ \else
+ \endgroup
+ \doubleexpandafter\firstofoneargument
+ \fi}
+
+\permanent\protected\def\overset#1#2%
+ {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}}
+
+\permanent\protected\def\underset#1#2%
+ {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}}
+
+%D The following code comes from \type {math-str.mkiv}.
+%D
+%D Here we implement a basic math alignment mechanism. Numbers are also handled. The macros
+%D \type {\startinnermath} and \type {\stopinnermath} can be overloaded in specialized
+%D modules.
+
+\installcorenamespace{mathinnerstart}
+\installcorenamespace{mathinnerstop}
+
+% \protected\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname}
+% \protected\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname}
+
+\permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal}
+\permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal}
+
+\permanent\protected\def\mathinnerstrut
+ {\doif{\formulaparameter\c!strut}\v!yes\strut}
+
+\permanent\protected\def\defineinnermathhandler#1#2#3%
+ {\setvalue{\??mathinnerstart#1}{#2}%
+ \setvalue{\??mathinnerstop #1}{#3}}
+
+\installtextracker
+ {formulas.boxes}
+ {\enforced\let\math_hbox\ruledhbox}
+ {\enforced\let\math_hbox\hbox}
+
+\let\math_hbox\hbox
+
+\newconstant\mathraggedstatus % normal left center right
+\newconstant\mathnumberstatus % nothing normal shift_right
+
+\newdimen\d_math_number_correction
+
+\def\math_box_llapped_math_no
+ {\ifcase\mathraggedstatus\or
+ \box\b_strc_formulas_number
+ \or
+ \llap{\box\b_strc_formulas_number}%
+ \or
+ \llap{\box\b_strc_formulas_number}%
+ \fi}
+
+\def\math_box_rlapped_math_no
+ {\ifcase\mathraggedstatus\or
+ \rlap{\box\b_strc_formulas_number}%
+ \or
+ \rlap{\box\b_strc_formulas_number}%
+ \or
+ \box\b_strc_formulas_number
+ \fi}
+
+\newconditional\c_strc_math_has_number
+\newconditional\c_strc_math_display_overflow
+\newconstant \c_strc_math_number_location
+\newdimen \d_strc_math_number_width
+\newdimen \d_strc_math_display_width
+\newbox \b_strc_math_display
+\newconstant \c_strc_formulas_frame_mode
+\newdimen \d_strc_math_indent
+\newconditional\c_strc_math_indent
+
+\let\d_strc_math_framed_width\displaywidth
+
+\setvalue{\??formulaoption\v!frame}%
+ {\edef\p_frame{\formulaparameter\c!frame}%
+ \ifx\p_frame\v!number
+ \c_strc_formulas_frame_mode\plustwo % inside frame
+ \else
+ \c_strc_formulas_frame_mode\plusone % outside frame
+ \fi}
+
+% mode: 0=no frame | 1=number inside frame | 2=number outside frame
+
+\def\strc_math_flush_aligned
+ {\ifcase\c_strc_math_vertical
+ \ifcase\mathraggedstatus\or\hfill\or\hfill\fi
+ \box\b_strc_math_display
+ \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi
+ \else
+ \ifconditional\c_strc_math_indent
+ \ifzeropt\d_strc_math_indent\else
+ \hangafter\plusone
+ \hangindent\d_strc_math_indent
+ \fi
+ \fi
+ \edef\p_interlinespace{\formulaparameter\c!interlinespace}%
+ \ifx\p_interlinespace\empty\else\baselineskip\p_interlinespace\fi
+ \global\d_strc_math_indent\zeropoint
+ \ifcase\mathraggedstatus\or\raggedleft\or\raggedcenter\or\raggedright\fi
+ \unhbox\b_strc_math_display
+ \fi}
+
+\def\strc_math_flush_box_normal
+ {\ifcase\c_strc_math_vertical
+ \hbox to \displaywidth\bgroup
+ \strc_math_flush_aligned
+ \egroup
+ \else
+ \strc_math_flush_aligned
+ \fi}
+
+\def\strc_math_flush_box_framed_common
+ {\setformulaframedparameter\c!align{\formulaparameter\c!align}%
+ \letformulaframedparameter\c!strut\v!no
+ \d_framed_formula\ht\b_strc_math_display
+ \ifcase\mathraggedstatus\or\hfill\or\hfill \fi
+ \inheritedformulaframedframed{\box\b_strc_math_display}%
+ \ifcase\mathraggedstatus\or \or\hfill\or\hfill\fi}
+
+% \def\strc_math_flush_box_framed_inline
+% {\letformulaframedparameter\c!location\empty
+% \letformulaframedparameter\c!width\displaywidth
+% \strc_math_flush_box_framed_common}
+
+\def\strc_math_flush_box_framed_display
+ {\let\currentformulaframed\currentformula
+ \letformulaframedparameter\c!location\v!formula
+ \setformulaframedparameter\c!width{\d_strc_math_framed_width}%
+ \strc_math_flush_box_framed_common}
+
+\def\strc_math_flush_box_framed_fit_inline
+ {\let\currentformulaframed\currentformula
+ \letformulaframedparameter\c!location\empty
+ \letformulaframedparameter\c!width\v!fit
+ \strc_math_flush_box_framed_common}
+
+\def\strc_math_flush_box_framed_fit_display
+ {\let\currentformulaframed\currentformula
+ \letformulaframedparameter\c!location\v!formula
+ \letformulaframedparameter\c!width\v!fit
+ \strc_math_flush_box_framed_common}
+
+% combiners
+
+\def\strc_math_flush_box
+ {\ifcase\c_strc_formulas_frame_mode
+ \strc_math_flush_box_normal
+ \else
+ \strc_math_flush_box_framed_display
+ \fi}
+
+\def\strc_math_number_right_normal
+ {\strc_math_flush_aligned
+ \hss % hss makes room for number
+ \math_box_llapped_math_no}
+
+\def\strc_math_number_left_normal
+ {\math_box_rlapped_math_no
+ \strc_math_flush_aligned
+ \hss} % hss makes room for number
+
+\def\strc_math_number_right_normal_outside
+ {\ifconditional\c_strc_formulas_tight
+ \strc_math_flush_box_framed_fit_display
+ \else
+ \strc_math_flush_box_framed_display
+ \fi
+ \hss % hss makes room for number
+ \math_box_llapped_math_no}
+
+\def\strc_math_number_left_normal_outside
+ {\math_box_rlapped_math_no
+ \hss % hss makes room for number
+ \ifconditional\c_strc_formulas_tight
+ \strc_math_flush_box_framed_fit_display
+ \else
+ \strc_math_flush_box_framed_display
+ \fi}
+
+\def\strc_math_number_right_normal_inside
+ {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup
+ \strc_math_flush_aligned
+ \hss
+ \math_box_llapped_math_no
+ \egroup
+ \strc_math_flush_box_framed_fit_inline}
+
+\def\strc_math_number_left_normal_inside
+ {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup
+ \math_box_rlapped_math_no
+ \hss
+ \strc_math_flush_aligned
+ \egroup
+ \strc_math_flush_box_framed_fit_inline}
+
+\def\strc_math_number_right_overflow
+ {\vpack\bgroup
+ \strc_math_flush_box
+ \par
+ \hpack to \displaywidth\bgroup
+ \hss
+ \math_box_llapped_math_no
+ \egroup
+ \egroup}
+
+\def\strc_math_number_left_overflow
+ {\vpack\bgroup
+ \hpack to \displaywidth\bgroup
+ \math_box_rlapped_math_no
+ \hss
+ \egroup
+ \strc_math_flush_box
+ \egroup}
+
+\def\strc_math_number_right_overflow_outside
+ {\vpack\bgroup
+ \strc_math_flush_box_framed_fit_inline
+ %\hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why
+ \hpack to \displaywidth\bgroup
+ \hss
+ \math_box_llapped_math_no
+ \egroup
+ \egroup}
+
+\def\strc_math_number_left_overflow_outside
+ {\vpack\bgroup
+ \hpack to \dimexpr\displaywidth-\d_framed_locator_lo\relax\bgroup
+ \math_box_rlapped_math_no
+ \hss
+ \egroup
+ \hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why
+ \strc_math_flush_box_framed_fit_inline
+ \egroup}
+
+\def\strc_math_number_right_overflow_inside
+ {\setbox\b_strc_math_display\vpack\bgroup
+ \box\b_strc_math_display
+ \hpack to \displaywidth\bgroup
+ \hss
+ \math_box_llapped_math_no
+ \hskip\d_framed_locator_ro
+ \egroup
+ \egroup
+ \strc_math_flush_box_framed_fit_inline}
+
+\def\strc_math_number_left_overflow_inside
+ {\setbox\b_strc_math_display\vpack\bgroup
+ \hpack to \displaywidth\bgroup
+ % \hskip\d_framed_locator_lo
+ \math_box_rlapped_math_no
+ \hss
+ \egroup
+ \box\b_strc_math_display
+ \egroup
+ \strc_math_flush_box_framed_fit_inline}
+
+% checkers
+
+\def\strc_math_number_check
+ {\d_strc_math_display_width\wd\b_strc_math_display
+ \ifconditional\c_strc_formulas_tight
+ \ifdim\d_strc_math_display_width>\displaywidth
+ \settrue\c_strc_math_display_overflow
+ \else
+ \displaywidth\d_strc_math_display_width
+ \setfalse\c_strc_math_display_overflow
+ \fi
+ \else
+ \ifdim\d_strc_math_display_width>\displaywidth
+ \settrue\c_strc_math_display_overflow
+ \else
+ \setfalse\c_strc_math_display_overflow
+ \fi
+ \fi}
+
+\def\strc_math_number_check_outside
+ {\d_strc_math_display_width\naturalwd\b_strc_math_display
+ \ifdim\dimexpr\d_strc_math_display_width+\d_framed_locator_lo+\d_framed_locator_ro\relax>\displaywidth
+ \settrue\c_strc_math_display_overflow
+ \else
+ \setfalse\c_strc_math_display_overflow
+ \fi
+ % still ok?
+ \ifnum\mathraggedstatus=\plustwo
+ \edef\d_strc_math_framed_width{\the\dimexpr\displaywidth-2\wd\b_strc_formulas_number\relax}%
+ \else
+ \edef\d_strc_math_framed_width{\the\dimexpr\displaywidth-\wd\b_strc_formulas_number\relax}%
+ \fi}
+
+\let\strc_math_number_check_inside\strc_math_number_check_outside
+
+% offsets
+
+\def\strc_math_number_check_offsets
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\inheritedformulaframedframed
+ {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}%
+ \endgroup}
+
+% tracing
+
+\def\strc_math_traced_state_yes
+ {\llap{\setbox\scratchbox\hbox{\infofont
+ \ifcase\mathraggedstatus unset\or right\or middle\or left\fi
+ \space
+ \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi
+ \space
+ \ifconditional\c_strc_math_display_overflow overflow\else fit\fi
+ \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}}
+
+\let\strc_math_traced_state\relax
+
+\installtextracker
+ {formulas.framed}
+ {\let\strc_math_traced_state\strc_math_traced_state_yes}
+ {\let\strc_math_traced_state\relax}
+
+% packaging
+
+\protected\def\strc_math_box_start#1%
+ {\hsize\displaywidth % \checkeddisplaymath
+ \global\mathnumberstatus\plusone
+ \mathraggedstatus#1\relax
+ %
+ \global\d_math_number_correction\zeropoint
+ %
+ \edef\p_location{\formulaparameter\c!location}%
+ \useformulacolorparameter\c!color
+ \c_strc_math_number_location\ifx\p_location\v!left\plusone\orelse\ifx\p_location\v!right\plustwo\else\zerocount\fi
+ %
+ %\strc_formulas_place_number % not here as we can have inner alignment numbers
+ \dontcomplain
+ \setbox\b_strc_math_display\math_hbox\bgroup % \checkeddisplaymath
+ \mathinnerstrut
+ \startforceddisplaymath}
+
+\def\strc_math_flush_number_no
+ {\ifcase\c_strc_math_vertical
+ \ifconditional\c_strc_math_display_overflow
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_flush_box_normal
+ \else
+ \strc_math_flush_box_framed_fit_inline
+ \fi
+ \else
+ \ifcase\c_strc_formulas_frame_mode
+ %\ifconditional\c_strc_formulas_tight
+ % \strc_math_flush_box_normal
+ %\else
+ \strc_math_flush_box_normal
+ %\fi
+ \else
+ \ifconditional\c_strc_formulas_tight
+ \strc_math_flush_box_framed_fit_inline
+ \else
+ \strc_math_flush_box_framed_display
+ \fi
+ \fi
+ \fi
+ \else
+ \strc_math_flush_box
+ \fi}
+
+\def\strc_math_flush_number_left
+ {\ifcase\c_strc_math_vertical
+ \ifconditional\c_strc_math_display_overflow
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_number_left_overflow
+ \or
+ \strc_math_number_left_overflow_outside
+ \or
+ \strc_math_number_left_overflow_inside
+ \fi
+ \else
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_number_left_normal
+ \or
+ \strc_math_number_left_normal_outside
+ \or
+ \strc_math_number_left_normal_inside
+ \fi
+ \fi
+ \else
+ \box\b_strc_formulas_number
+ \hfill
+ \strc_math_flush_aligned
+ \fi}
+
+\def\strc_math_flush_number_right
+ {\ifcase\c_strc_math_vertical
+ \ifconditional\c_strc_math_display_overflow
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_number_right_overflow
+ \or
+ \strc_math_number_right_overflow_outside
+ \or
+ \strc_math_number_right_overflow_inside
+ \fi
+ \else
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_number_right_normal
+ \or
+ \strc_math_number_right_normal_outside
+ \or
+ \strc_math_number_right_normal_inside
+ \fi
+ \fi
+ \else
+ \strc_math_flush_aligned
+ \hfill
+ \box\b_strc_formulas_number
+ \fi}
+
+\protected\def\strc_math_box_stop
+ {\stopforceddisplaymath
+ \egroup
+ % check number
+ \d_strc_math_number_width\wd\b_strc_formulas_number
+ %
+ \ifcase\mathnumberstatus
+ \setfalse\c_strc_math_has_number
+ \or\ifzeropt\d_strc_math_number_width
+ \setfalse\c_strc_math_has_number
+ \else
+ \settrue\c_strc_math_has_number
+ \fi\fi
+ % preroll left and right offsets
+ \ifcase\c_strc_formulas_frame_mode
+ % no frame
+ \else
+ \strc_math_number_check_offsets
+ \fi
+ \ifcase\c_strc_formulas_frame_mode
+ \strc_math_number_check
+ \or
+ \strc_math_number_check_outside
+ \else
+ \strc_math_number_check_inside
+ \fi
+ \noindent % \noindentation % not \dontleavehmode
+ \hskip\d_strc_formulas_display_margin_left % was kern but that doesn't indent
+ \strc_math_traced_state
+ \ifcase\c_strc_math_vertical
+ \hbox to \displaywidth \bgroup
+ \or
+ \vbox \bgroup \hsize\displaywidth
+ \or
+ \bgroup \hsize\displaywidth
+ \fi
+ \ifcase\mathnumberstatus
+ \strc_math_flush_box
+ \or % status 1
+ \ifcase\c_strc_math_number_location
+ \strc_math_flush_box
+ \or % number left
+ \ifzeropt\wd\b_strc_formulas_number
+ \strc_math_flush_number_no
+ \else
+ \strc_math_flush_number_left
+ \fi
+ \else % number right
+ \ifzeropt\wd\b_strc_formulas_number
+ \strc_math_flush_number_no
+ \else
+ \strc_math_flush_number_right
+ \fi
+ \fi
+ \or % status 2
+ \hskip\d_math_number_correction % probably no longer used
+ \strc_math_flush_box
+ \hss
+ \else
+ \strc_math_flush_box
+ \fi
+ \ifcase\c_strc_math_vertical
+ \or
+ \or
+ \par
+ \fi
+ \egroup}
+
+\defineinnermathhandler\v!left {\strc_math_box_start\plusone }{\strc_math_box_stop}
+\defineinnermathhandler\v!middle {\strc_math_box_start\plustwo }{\strc_math_box_stop}
+\defineinnermathhandler\v!right {\strc_math_box_start\plusthree}{\strc_math_box_stop}
+\defineinnermathhandler\v!flushleft {\strc_math_box_start\plusthree}{\strc_math_box_stop}
+\defineinnermathhandler\v!center {\strc_math_box_start\plustwo }{\strc_math_box_stop}
+\defineinnermathhandler\v!flushright{\strc_math_box_start\plusone }{\strc_math_box_stop}
+\defineinnermathhandler\v!normal {\strc_math_box_start\plustwo }{\strc_math_box_stop}
+
+%D Some inline math tweak.
+
+\appendtoks
+ \ifcase\mathnestinglevel\or
+ % 4=disable 6=only when no spaces
+ \mathsurroundskip\mathematicsparameter\c!textdistance\relax
+ \ifzeropt\mathsurroundskip
+ \ifzeropt\gluestretch\mathsurroundskip
+ \ifzeropt\glueshrink\mathsurroundskip
+ \mathsurroundmode\plussix
+ \else
+ \mathsurroundskip\zeropoint
+ \mathsurroundmode\plusfour
+ \fi
+ \else
+ \mathsurroundmode\plussix
+ \fi
+ \else
+ \mathsurroundmode\plussix
+ \fi
+ \else
+ \mathsurroundmode\plusfour
+ \mathsurroundskip\zeropoint
+ \fi
+\to \everymathematics
+
+\setupmathematics
+ [\c!textdistance=\zeropoint]
+
+%D This is an experiment. No fancy spacing and alignments here. If we ever
+%D go that route it might result in incompatible rendering.
+
+\permanent\protected\def\startsplitformula
+ {\ifhmode
+ \par
+ \fi
+ \begingroup
+ \beforedisplayspace
+ % subset of \everydisplay:
+ \c_attr_mathmode\plusone
+ \settrue \indisplaymath
+ % end of subset
+ \informulatrue}
+
+\permanent\protected\def\stopsplitformula
+ {\afterdisplayspace
+ \endgroup}
+
+\protect \endinput
+
+% \placeformula \startformula[-] \startmatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopmatrix \stopformula
+
+% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}]
+
+% \placeformula \startformula[-] \startbordermatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopbordermatrix \stopformula
diff --git a/tex/context/base/mkiv/math-def.mkiv b/tex/context/base/mkiv/math-def.mkiv
index 641f7411e..14ceeb61e 100644
--- a/tex/context/base/mkiv/math-def.mkiv
+++ b/tex/context/base/mkiv/math-def.mkiv
@@ -1,4 +1,4 @@
-%D \module
+ %D \module
%D [ file=math-tex,
%D version=2001.04.12,
%D title=\CONTEXT\ Math Macros,
@@ -80,6 +80,8 @@
{\savenormalmeaning{#1}%
\expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}}
+\pushoverloadmode
+
\setoperatorlimits \int \intlimits
\setoperatorlimits \iint \intlimits
\setoperatorlimits \iiint \intlimits
@@ -90,6 +92,8 @@
\setoperatorlimits \ointclockwise \intlimits
\setoperatorlimits \ointctrclockwise \intlimits
+\popoverloadmode
+
%D \macros
%D {centercolon, colonminus, minuscolon, colonequals, equalscolon,
%D colonapprox, approxcolon, colonsim, simcolon, coloncolon,
@@ -131,6 +135,8 @@
%D The next macros take care of the space between the colon and the
%D relation symbol.
+\pushoverloadmode
+
\definemathcommand [colonsep] {\mkern-1.2mu}
\definemathcommand [doublecolonsep] {\mkern-0.9mu}
@@ -154,6 +160,8 @@
\definemathcommand [coloncolonsim] [rel] {\coloncolon\colonsep\sim}
\definemathcommand [simcoloncolon] [rel] {\sim\coloncolon\colonsep}
+\popoverloadmode
+
% \appendtoks
% \def\over{\primitive\over}%
% \to \everymathematics
diff --git a/tex/context/base/mkiv/math-fen.mkiv b/tex/context/base/mkiv/math-fen.mkiv
index 246ff989d..d7c67b7e3 100644
--- a/tex/context/base/mkiv/math-fen.mkiv
+++ b/tex/context/base/mkiv/math-fen.mkiv
@@ -335,6 +335,8 @@
%D A bonus:
+\pushoverloadmode
+
\unexpanded\def\Lparenthesis {\math_fenced_fenced_start{parenthesis}} \unexpanded\def\Rparenthesis {\math_fenced_fenced_stop {parenthesis}}
\unexpanded\def\Lbracket {\math_fenced_fenced_start{bracket}} \unexpanded\def\Rbracket {\math_fenced_fenced_stop {bracket}}
\unexpanded\def\Lbrace {\math_fenced_fenced_start{brace}} \unexpanded\def\Rbrace {\math_fenced_fenced_stop {brace}}
@@ -394,14 +396,20 @@
% \left| \frac{1}{e} \right|
% \stopformula
+\popoverloadmode
+
\installcorenamespace{mathleft}
\installcorenamespace{mathright}
\installcorenamespace{mathmiddle}
+\pushoverloadmode
+
\unexpanded\def\left {\afterassignment\math_left \let\nexttoken}
\unexpanded\def\right {\afterassignment\math_right \let\nexttoken}
\unexpanded\def\middle{\afterassignment\math_middle\let\nexttoken}
+\popoverloadmode
+
\let\leftorright\relax
\newconditional\c_math_fenced_done
@@ -565,6 +573,8 @@
% The names in char-def.lua (historic mess):
+\pushoverloadmode
+
\let\lbrack \lbracket
\let\rbrack \rbracket
\let\lceiling \lceil
@@ -634,6 +644,8 @@
\installmathfencepair \< \Langle \> \Rangle
\installmathfencepair \| \Lbar \| \Rbar
+\popoverloadmode
+
%D As we have overloaded \type {\left} and \type {\right} we also need a more
%D clever version of the following:
diff --git a/tex/context/base/mkiv/math-frc.mkiv b/tex/context/base/mkiv/math-frc.mkiv
index 8b068bc6c..1b0149f96 100644
--- a/tex/context/base/mkiv/math-frc.mkiv
+++ b/tex/context/base/mkiv/math-frc.mkiv
@@ -630,8 +630,6 @@
%D More fracking (for Alan):
-\def\s!vfrac{vfrac}
-
\unexpanded\def\math_frac_colored_vulgar#1#2%
{\savecolor
\colo_helpers_activate\p_math_fractions_color
diff --git a/tex/context/base/mkiv/math-frc.mkxl b/tex/context/base/mkiv/math-frc.mkxl
new file mode 100644
index 000000000..b6c77f4bb
--- /dev/null
+++ b/tex/context/base/mkiv/math-frc.mkxl
@@ -0,0 +1,753 @@
+%D \module
+%D [ file=math-frc,
+%D version=2013.04.06, % 2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fractions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / Fractions}
+
+\unprotect
+
+%D I need to check it all again as there was a bug in luatex with dimensions that could
+%D resulted in side effects that made me mess with spacing.
+
+\unexpanded\def\topstrut{\vrule\s!width\zeropoint\s!height\strutht\s!depth\zeropoint\relax}
+\unexpanded\def\botstrut{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp\relax}
+
+\unexpanded\def\mathtopstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\ht\scratchbox\s!depth\zeropoint\relax}
+\unexpanded\def\mathbotstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\dp\scratchbox\relax}
+
+%D This module is reimplemented in \MKIV\ style.
+
+\registerctxluafile{math-frc}{}
+
+%D \macros
+%D {frac, xfrac, xxfrac}
+%D
+%D This is another one Tobias asked for. It replaces the primitive \type
+%D {\over}. We also take the opportunity to handle math style restoring,
+%D which makes sure units and chemicals come out ok. The \type {\frac}
+%D macro kind of replaces the awkward \type {\over} primitive. Say that
+%D we have the following formulas:
+%D
+%D \startbuffer[sample]
+%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$
+%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$
+%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$
+%D \stopbuffer
+%D
+%D \typebuffer[sample]
+%D
+%D With the most straightforward definitions, we get:
+%D
+%D \startbuffer[code]
+%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
+%D
+%D \def\frac {\dofrac\mathstyle}
+%D \def\xfrac {\dofrac\scriptstyle}
+%D \def\xxfrac{\dofrac\scriptscriptstyle}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D Since this does not work well, we can try:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}}
+%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D This for sure looks better than:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}}
+%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D So we stick to the next definitions (watch the local overloading of
+%D \type {\xfrac}).
+%D
+%D In the meantime, in \LUATEX, we have better control over styles so the
+%D following macros are different from the \MKII\ ones.
+
+% obsolete, is now c!mathstyle
+%
+% 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle
+%
+% $\mathfracmode0 \frac{1}{2}$
+% $\mathfracmode1 \frac{1}{2}$
+% $\mathfracmode2 \frac{1}{2}$
+% $\mathfracmode3 \frac{1}{2}$
+% $\mathfracmode4 \frac{1}{2}$
+% $\mathfracmode5 \frac{1}{2}$
+%
+% we keep the constant for a while
+
+\setnewconstant\mathfracmode\zerocount
+
+\installcorenamespace{mathfractions}
+\installcorenamespace{mathfractionstyle}
+\installcorenamespace{mathfractionalternative}
+
+\installcommandhandler \??mathfractions {mathfraction} \??mathfractions
+
+\let\setupmathfractions\setupmathfraction
+
+% color only applies to rule, use regular color for rest
+
+\setupmathfractions
+ [\c!mathstyle=,
+ \c!alternative=\v!inner,
+ \c!margin=\zeropoint,
+ \c!rulethickness=.25\exheight,
+ \c!left=0x2E,
+ \c!right=0x2E,
+ \c!strut=\v!yes,
+ \c!topdistance=,
+ \c!bottomdistance=,
+ \c!rule=\v!auto]
+
+\appendtoks
+ \setuevalue{\currentmathfraction}{\math_frac{\currentmathfraction}}%
+\to \everydefinemathfraction
+
+% Sometimes users want control over the distances:
+
+\let\math_fraction_set_distance\relax
+
+\appendtoks
+ \math_fraction_set_distance
+\to \everymathematics
+
+% why only displaystyle .. a bit weak
+
+\unexpanded\def\math_fraction_set_distance_top
+ {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top
+ \relax}
+
+\unexpanded\def\math_fraction_set_distance_bot
+ {\Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot
+ \relax}
+
+\unexpanded\def\math_fraction_set_distance_all
+ {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top
+ \Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot
+ \relax}
+
+\appendtoks
+ \ifx\currentmathfraction\empty
+ \edef\m_math_fraction_distance_top{\mathfractionparameter\c!topdistance}%
+ \edef\m_math_fraction_distance_bot{\mathfractionparameter\c!bottomdistance}%
+ \ifx\m_math_fraction_distance_top\empty
+ \ifx\m_math_fraction_distance_bot\empty
+ \let\math_fraction_set_distance\relax
+ \else
+ \let\math_fraction_set_distance\math_fraction_set_distance_bot
+ \fi
+ \else
+ \ifx\m_math_fraction_distance_bot\empty
+ \let\math_fraction_set_distance\math_fraction_set_distance_top
+ \else
+ \let\math_fraction_set_distance\math_fraction_set_distance_all
+ \fi
+ \fi
+ \fi
+\to \everysetupmathfraction
+
+% So far for control.
+
+\installcorenamespace{mathfractionstrut}
+
+\def\math_frac_no_strut
+ {\enforced\let\m_fractions_strut_top\relax
+ \enforced\let\m_fractions_strut_bot\relax}
+
+\setvalue{\??mathfractionstrut\v!yes}%
+ {\enforced\let\m_fractions_strut_top\mathstrut
+ \enforced\let\m_fractions_strut_bot\mathstrut}
+
+\setvalue{\??mathfractionstrut\v!math}%
+ {\enforced\let\m_fractions_strut_top\mathstrut
+ \enforced\let\m_fractions_strut_bot\mathstrut}
+
+\letvalue{\??mathfractionstrut\v!no}\math_frac_no_strut
+
+\setvalue{\??mathfractionstrut\v!tight}%
+ {\enforced\let\m_fractions_strut_top\mathbotstrut % indeed swapped name
+ \enforced\let\m_fractions_strut_bot\mathtopstrut} % indeed swapped name
+
+\math_frac_no_strut
+
+\newdimen\d_math_fraction_margin
+
+\unexpanded\def\math_frac#1%
+ {\begingroup
+ \edef\currentmathfraction{#1}%
+ %
+ \edef\p_math_fraction_fences{\mathfractionparameter\c!fences}%
+ \ifx\p_math_fraction_fences\empty \else
+ \math_fenced_fenced_start\p_math_fraction_fences
+ \fi
+ %
+ \d_math_fraction_margin\mathfractionparameter\c!margin
+ %
+ \edef\p_math_fractions_color{\mathfractionparameter\c!color}%
+ %
+ \edef\p_math_fractions_strut{\mathfractionparameter\c!strut}%
+ \ifcsname\??mathfractionstrut\p_math_fractions_strut\endcsname
+ \lastnamedcs
+ \else
+ \math_frac_no_strut
+ \fi
+ %
+ \ifx\p_math_fractions_color\empty
+ \expandafter\math_frac_normal
+ \else
+ \expandafter\math_frac_colored
+ \fi}
+
+\unexpanded\def\math_frac_wrapup
+ {\ifx\p_math_fraction_fences\empty \else
+ \math_fenced_fenced_stop\p_math_fraction_fences
+ \fi
+ \endgroup}
+
+\unexpanded\def\math_frac_colored#1#2%
+ {\savecolor
+ \colo_helpers_activate\p_math_fractions_color
+ \math_frac_normal{\restorecolor#1}{\restorecolor#2}}
+
+\unexpanded\def\math_frac_normal
+ {\expandnamespaceparameter\??mathfractionalternative\mathfractionparameter\c!alternative\v!inner}
+
+% we use utfchar anyway so we can as well do all at the lua end
+
+\def\math_frac_no_delim{0x2E}
+
+\def\math_frac_command
+ {\clf_mathfraction
+ {\mathfractionparameter\c!rule}%
+ \ifx\p_math_fraction_fences\empty
+ \mathfractionparameter\c!left \space
+ \mathfractionparameter\c!right\space
+ \else
+ \math_frac_no_delim\space
+ \math_frac_no_delim\space
+ \fi
+ \dimexpr\mathfractionparameter\c!rulethickness\relax
+ \relax}
+
+% Having a \withmarginornot{#1}{#2} makes not much sense nor do 4 tests or 4 redundant
+% kerns (longer node lists plus possible interference). A split in normal and margin
+% also makes testing easier. When left and right margins are needed we might merge the
+% variants again. After all, these are not real installers.
+
+% the denominator is in cramped!
+
+\setvalue{\??mathfractionalternative\v!inner}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_inner_normal
+ \else
+ \expandafter\math_fraction_inner_margin
+ \fi}
+
+\setvalue{\??mathfractionalternative\v!outer}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_outer_normal
+ \else
+ \expandafter\math_fraction_outer_margin
+ \fi}
+
+\setvalue{\??mathfractionalternative\v!both}%
+ {\ifcase\d_math_fraction_margin
+ \expandafter\math_fraction_both_normal
+ \else
+ \expandafter\math_fraction_both_margin
+ \fi}
+
+% todo: store first state and reuse second time
+
+\def\math_fraction_inner_normal#1#2%
+ {\Ustack{%
+ {%
+ {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}%
+ \math_frac_command
+ {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\def\math_fraction_outer_normal#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\m_fractions_strut_top#1}%
+ \math_frac_command
+ {\m_fractions_strut_bot#2}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\def\math_fraction_both_normal#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}%
+ \math_frac_command
+ {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\def\math_fraction_inner_margin#1#2%
+ {\Ustack{%
+ {%
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}%
+ \kern\d_math_fraction_margin}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\def\math_fraction_outer_margin#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\kern\d_math_fraction_margin
+ \m_fractions_strut_top#1%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \m_fractions_strut_bot#2%
+ \kern\d_math_fraction_margin}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\def\math_fraction_both_margin#1#2%
+ {\Ustack{%
+ \usemathstyleparameter\mathfractionparameter
+ {%
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1%
+ \kern\d_math_fraction_margin}%
+ \math_frac_command
+ {\kern\d_math_fraction_margin
+ \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2%
+ \kern\d_math_fraction_margin}%
+ }%
+ }%
+ \math_frac_wrapup}
+
+\definemathfraction[xfrac] [\c!alternative=\v!inner,\c!mathstyle=\s!script]
+\definemathfraction[xxfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript]
+
+\let\normalxfrac\xfrac
+
+\unexpanded\def\xfrac#1#2{\normalxfrac{\let\xfrac\xxfrac#1}{\let\xfrac\xxfrac#2}}
+
+%D Spacing (sensitive for definition of \triggermathstyle:
+
+% \ifcase\contextlmtxmode
+
+\unexpanded\def\nomathfractiongaps {\normalexpanded{\math_no_fraction_gaps \mathstyletrigger\mathstyle}} % maybe collect settings
+\unexpanded\def\overlaymathfractiongaps{\normalexpanded{\math_overlay_fraction_gaps\mathstyletrigger\mathstyle}} % maybe collect settings
+
+\unexpanded\def\math_no_fraction_gaps#1%
+ {\Umathfractionnumup #1\zeropoint
+ \Umathfractiondenomdown#1\zeropoint}
+
+\unexpanded\def\math_overlay_fraction_gaps#1%
+ {\Umathfractionnumup #1\zeropoint
+ \Umathfractionnumvgap #1\zeropoint
+ %Umathfractionrule #1\zeropoint
+ \Umathfractiondenomvgap#1\zeropoint
+ \Umathfractiondenomdown#1\zeropoint}
+
+% \else
+
+% \unexpanded\def\math_no_fraction_gaps
+% {\Umathfractionnumup \mathstyle\zeropoint
+% \Umathfractiondenomdown\mathstyle\zeropoint}
+%
+% \unexpanded\def\math_overlay_fraction_gaps
+% {\Umathfractionnumup \mathstyle\zeropoint
+% \Umathfractionnumvgap \mathstyle\zeropoint
+% %Umathfractionrule \mathstyle\zeropoint
+% \Umathfractiondenomvgap\mathstyle\zeropoint
+% \Umathfractiondenomdown\mathstyle\zeropoint}
+
+% \fi
+
+\installcorenamespace{mathfractiondistance}
+
+\letvalue{\??mathfractiondistance\v!none }\nomathfractiongaps
+\letvalue{\??mathfractiondistance\v!no }\nomathfractiongaps
+\letvalue{\??mathfractiondistance\v!overlay}\overlaymathfractiongaps
+
+\setupmathfractions
+ [\c!distance=\v!none]
+
+\appendtoks
+ \edef\p_distance{\rootmathfractionparameter\c!distance}%
+ \ifx\p_distance\empty\else
+ \ifcsname\??mathfractiondistance\p_distance\endcsname
+ \lastnamedcs
+ \fi
+ \fi
+\to \everymathematics
+
+% theshold is new!
+
+\let\math_fraction_set_threshold_inline \relax
+\let\math_fraction_set_threshold_display\relax
+
+\appendtoks
+ \math_fraction_set_threshold_inline
+ \math_fraction_set_threshold_display
+\to \everymathematics
+
+\appendtoks
+ \ifx\currentmathfraction\empty
+ \edef\p_threshold{\mathfractionparameter\c!inlinethreshold}%
+ \ifx\p_threshold\empty
+ \let\math_fraction_set_threshold_inline\relax
+ \else\ifx\p_threshold\v!auto
+ \let\math_fraction_set_threshold_inline\relax
+ \else
+ \let\math_fraction_set_threshold_inline\math_fraction_set_theshold_inline
+ \fi\fi
+ \edef\p_threshold{\mathfractionparameter\c!displaythreshold}%
+ \ifx\p_threshold\empty
+ \let\math_fraction_set_threshold_display\relax
+ \else\ifx\p_threshold\v!auto
+ \let\math_fraction_set_threshold_display\relax
+ \else
+ \let\math_fraction_set_threshold_display\math_fraction_set_theshold_display
+ \fi\fi
+ \fi
+\to \everysetupmathfraction
+
+\def\math_fraction_set_theshold_inline
+ {\edef\p_threshold{\mathfractionparameter\c!inlinethreshold}%
+ \Umathfractiondelsize\textstyle \p_threshold\dimexpr\textface\relax
+ \Umathfractiondelsize\scriptstyle \p_threshold\dimexpr\scriptface\relax
+ \Umathfractiondelsize\scriptscriptstyle\p_threshold\dimexpr\scriptscriptface\relax}
+
+\def\math_fraction_set_theshold_display
+ {\edef\p_threshold{\mathfractionparameter\c!displaythreshold}%
+ \Umathfractiondelsize\displaystyle \p_threshold\dimexpr\textface\relax}
+
+%D \macros
+%D {dfrac, tfrac, frac, dbinom, tbinom, binom}
+%D
+%D \startbuffer
+%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$
+%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+% $$
+% {{a}\over{b}} +
+% {{a}\overwithdelims(){b}} +
+% {{a}\atopwithdelims(){b}} +
+% {{a}\abovewithdelims()\zeropoint{b}} +
+% \left({{a}\over{b}}\right)
+% $$
+
+% \dorecurse {10} { % weird
+% $$ {{a}\abovewithdelims()#1pt{b}} $$
+% }
+
+\definemathfraction[i:frac] [\c!alternative=\v!inner,\c!mathstyle=] % was script and then small but nothing needed
+\definemathfraction[i:tfrac][\c!alternative=\v!inner,\c!mathstyle=\s!text] % was script (before luatex fix)
+\definemathfraction[i:sfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript]
+\definemathfraction[i:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display]
+
+\definemathfraction[d:frac] [\c!alternative=\v!inner,\c!mathstyle=\s!cramped] % was cramped,text
+\definemathfraction[d:tfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!text}] % was cramped,script (before luatex fix)
+\definemathfraction[d:sfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!scriptscript}]
+\definemathfraction[d:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display]
+
+%D \unexpanded\def\ShowMathFractions#1#2%
+%D {\dontleavehmode
+%D \begingroup
+%D \showmathstruts
+%D \mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}%
+%D \endgroup}
+%D
+%D The default \type {tfrac}, \type {frac} and \type \sfrac} look like this:
+%D
+%D \blank
+%D \ShowMathFractions{a}{a}\par
+%D \ShowMathFractions{1}{x}\par
+%D \ShowMathFractions{a}{b}\par
+%D \ShowMathFractions{1}{b}\par
+%D \blank
+
+\unexpanded\def\frac {\csname\inlineordisplaymath id:frac\endcsname}
+\unexpanded\def\tfrac{\csname\inlineordisplaymath id:tfrac\endcsname}
+\unexpanded\def\sfrac{\csname\inlineordisplaymath id:sfrac\endcsname}
+\unexpanded\def\dfrac{\csname\inlineordisplaymath id:dfrac\endcsname}
+
+\definemathfraction[ams] [\c!strut=\v!no,\c!alternative=\v!outer]
+\definemathfraction[i:ams:frac][ams][\c!mathstyle={\s!cramped,\s!text}]
+\definemathfraction[d:ams:frac][ams][\c!mathstyle={\s!cramped,\s!display}]
+
+\unexpanded\def\ctxfrac{\csname\inlineordisplaymath id:frac\endcsname}
+\unexpanded\def\amsfrac{\csname\inlineordisplaymath id:ams:frac\endcsname}
+
+% \appendtoks
+% \doifelse{\mathfractionparameter\c!option}{ams}%
+% {\let\frac\amsfrac}%
+% {\let\frac\ctxfrac}%
+% \to \everysetupmathfraction
+
+\appendtoks
+ \doifelse{\mathematicsparameter\c!fractions}{ams}%
+ {\let\frac\amsfrac}%
+ {\let\frac\ctxfrac}%
+\to \everysetupmathematics
+
+% \definemathfraction[ddfrac][\c!mathstyle=\s!display]
+% \definemathfraction[ttfrac][\c!mathstyle=\s!text]
+% \definemathfraction[ssfrac][\c!mathstyle=\s!script]
+
+% \unexpanded\def\binom #1#2{{\Ustack {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+% \unexpanded\def\dbinom#1#2{{\displaystyle{{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+% \unexpanded\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+
+\definemathfraction
+ [binom]
+ [\c!alternative=\v!outer,
+ \c!rule=\v!no,
+ \c!left=0x28,
+ \c!right=0x29,
+ \c!mathstyle=\s!auto]
+
+\definemathfraction
+ [dbinom]
+ [binom]
+ [\c!mathstyle=\s!display]
+
+\definemathfraction
+ [tbinom]
+ [binom]
+ [\c!mathstyle=\s!text]
+
+%D \macros
+%D {cfrac}
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Now we can align every combination we want:
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$
+%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+\unexpanded\def\cfrac
+ {\doifelsenextoptionalcs\math_cfrac_yes\math_cfrac_nop}
+
+\def\math_cfrac_nop {\math_cfrac_indeed[cc]}
+\def\math_cfrac_yes[#1]{\math_cfrac_indeed[#1cc]}
+
+\def\math_cfrac_indeed[#1#2#3]#4#5%
+ {{\displaystyle
+ \frac
+ {\strut
+ \ifx r#1\hfill\fi#4\ifx l#1\hfill\fi}%
+ {\ifx r#2\hfill\fi#5\ifx l#2\hfill\fi}%
+ \kern-\nulldelimiterspace}}
+
+%D \macros
+%D {splitfrac, splitdfrac}
+%D
+%D Occasionally one needs to typeset multi||line fractions.
+%D These commands use \tex{genfrac} to create such fractions.
+%D
+%D \startbuffer
+%D \startformula
+%D a=\frac{
+%D \splitfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D =\frac{
+%D \splitdfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D These macros are based on Michael J.~Downes posting on
+%D comp.text.tex on 2001/12/06 but adapted a bit.
+
+\unexpanded\def\splitfrac #1#2%
+ {{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}}
+
+\unexpanded\def\splitdfrac#1#2%
+ {{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}}
+
+%D For testing:
+
+% \unexpanded\def\ShowMathFractions#1#2%
+% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}}
+
+%D More fracking (for Alan):
+
+\unexpanded\def\math_frac_colored_vulgar#1#2%
+ {\savecolor
+ \colo_helpers_activate\p_math_fractions_color
+ {\restorecolor#1}\Uskewed/{\restorecolor#2}}
+
+\unexpanded\def\math_frac_normal_vulgar#1#2%
+ {{#1}\Uskewed/{#2}}
+
+\unexpanded\def\vfrac#1#2%
+ {\bgroup
+ \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}%
+ \ifx\p_math_fractions_color\empty
+ \expandafter\math_frac_normal_vulgar
+ \else
+ \expandafter\math_frac_colored_vulgar
+ \fi
+ {#1}%
+ {#2}%
+ \egroup}
+
+\appendtoks
+ \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}%
+ \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}%
+ \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle
+ \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle
+ \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle
+ \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle
+ \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle
+ \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle
+\to \everysetupmathfraction
+
+\setupmathfraction
+ [\s!vfrac]
+ [\c!hfactor=.2,
+ \c!vfactor=.1]
+
+\protect \endinput
+
+% I have no clue what \mthfrac and \mthsqrt are supposed to do but
+% I guess that it can be done with tweaking luatex's math parameters.
+% Otherwise I'll write something from scratch.
+
+% \def\math_stylebuilders_frac#1#2#3#4#5#6#7%
+% {\begingroup
+% \mathsurround\zeropoint
+% \setbox0\hbox{$#1 #6$}%
+% \setbox2\hbox{$#1 #7$}%
+% \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi
+% \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}%
+% \mathord{\vcenter{{\offinterlineskip
+% \hbox to \dimen0{\hss\box0\hss}%
+% \kern\ht4%
+% \hbox to \dimen0{\hss\copy4\hss}%
+% \kern\ht4%
+% \hbox to \dimen0{\hss\box2\hss}}}}%
+% \endgroup}
+%
+% \def\math_stylebuilders_sqrt#1#2#3#4#5%
+% {\begingroup
+% \mathsurround\zeropoint
+% \setbox0\hbox{$#1 #5$}%
+% \ht0\dimexpr1.05\ht0+\onepoint\relax
+% \dp0\dimexpr1.05\dp0+\onepoint\relax
+% \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}%
+% \delimitershortfall\zeropoint
+% \nulldelimiterspace\zeropoint
+% \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point?
+% \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
+% \endgroup}
+%
+% \def\mthfrac#1#2#3#4#5{\mathchoice
+% {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}%
+% {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
+%
+% \def\mthsqrt#1#2#3{\mathchoice
+% {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}%
+% {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}}
+
+% \unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]}
+% \unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]}
+
+% used for prototyping \Uskewed
+%
+% \unexpanded\def\skewedfractiona#1#2{%
+% \raise
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax$%
+% \egroup
+% \hbox to \zeropoint\bgroup
+% \hss$\textstyle/$\hss
+% \egroup
+% \lower
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax\scriptstyle#2$%
+% \egroup
+% }
+%
+% \unexpanded\def\skewedfractionb#1#2{%
+% \raise
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax$%
+% \egroup
+% \hbox to \zeropoint\bgroup
+% \hss$\textstyle/$\hss
+% \egroup
+% \lower
+% \Umathskewedfractionvgap\textstyle
+% \hbox\bgroup
+% $\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax\scriptstyle#2$%
+% \egroup
+% }
+%
+% $\skewedfractiona{1}{2}$
+% $\skewedfractionb{1}{2}$
diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua
index 0af9a2121..4f7e803d0 100644
--- a/tex/context/base/mkiv/math-ini.lua
+++ b/tex/context/base/mkiv/math-ini.lua
@@ -243,6 +243,8 @@ local f_root = formatters[ [[\ugdef\%s{\Uroot "%X "%X }]] ]
----- f_char = formatters[ [[\ugdef\%s{\Umathchar "%X "%X "%X }]]
local f_char = formatters[ [[\Umathchardef\%s "%X "%X "%X ]] ]
+local texmathchardef = tex.mathchardef
+
local setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing
if class == classes.accent then
ctx_sprint(f_accent(name,family,slot))
@@ -264,6 +266,8 @@ local setmathsymbol = function(name,class,family,slot) -- hex is nicer for traci
ctx_sprint(f_radical(name,family,slot))
elseif class == classes.root then
ctx_sprint(f_root(name,family,slot))
+ elseif texmathchardef then
+ texmathchardef(name,class,family,slot,"permanent")
else
-- beware, open/close and other specials should not end up here
ctx_sprint(f_char(name,class,family,slot))
diff --git a/tex/context/base/mkiv/math-ini.mkxl b/tex/context/base/mkiv/math-ini.mkxl
index 427d79d45..6e6018896 100644
--- a/tex/context/base/mkiv/math-ini.mkxl
+++ b/tex/context/base/mkiv/math-ini.mkxl
@@ -32,7 +32,7 @@
%
% plus two new math styles: larger/smaller
%
-% \unexpanded\def\Umathshow#1%
+% \protected\def\Umathshow#1%
% {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}}
%D This module provides namespaces for math fonts, thereby permitting mixed usage of
@@ -72,8 +72,8 @@
\registerctxluafile{math-ttv}{}
\registerctxluafile{math-map}{optimize}
\registerctxluafile{math-ren}{}
-\registerctxluafile{math-noa}{optimize}
-\registerctxluafile{math-tag}{}
+\registerctxluafile{math-noa}{autosuffix,optimize}
+\registerctxluafile{math-tag}{autosuffix}
\registerctxluafile{math-fbk}{}
\registerctxluafile{math-dir}{}
\registerctxluafile{math-spa}{}
@@ -100,7 +100,7 @@
\def\Umathbotaccent{\Umathaccent \s!bottom }
\def\Umathtopaccent{\Umathaccent \s!top }
-\def\Umathaccents {\Umathaccent \s!both }
+\def\Umathaccents {\Umathaccent \s!both } % strange highlighting
\ifdefined\Umathcharclass \else
\def\Umathcharclass{\numexpr\cldcontext{tex.getmathcode(token.scan_int())[1]}\relax}
@@ -142,9 +142,9 @@
\c_attr_displaymath\plusone
\to \everybeforedisplayformula
-\setnewconstant\defaultmathfamily \zerocount % 255
+\defaultmathfamily \zerocount % 255
-\unexpanded\def\resetmathattributes{\clf_resetmathattributes}
+\permanent\protected\def\resetmathattributes{\clf_resetmathattributes}
% handy
@@ -158,25 +158,25 @@
\settrue\indisplaymath
\to \everydisplay
-\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
+\permanent\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
-\unexpanded\def\forcedisplaymath
+\permanent\protected\def\forcedisplaymath
{\ifmmode
\displaystyle
\settrue\indisplaymath
\fi}
-\unexpanded\def\startforceddisplaymath
+\permanent\protected\def\startforceddisplaymath
{\startimath
\displaystyle
\begingroup
\settrue\indisplaymath}
-\unexpanded\def\stopforceddisplaymath
+\permanent\protected\def\stopforceddisplaymath
{\endgroup
\stopimath}
-\unexpanded\def\startpickupmath % for the moment private
+\permanent\protected\def\startpickupmath % for the moment private
{\ifconditional\indisplaymath
\startforceddisplaymath
\let\stoppickupmath\stopforceddisplaymath
@@ -187,7 +187,7 @@
\let\stoppickupmath\relax
-% \unexpanded\def\rawmathcharacter#1% slow but only for tracing
+% \protected\def\rawmathcharacter#1% slow but only for tracing
% {\begingroup
% \ifmmode
% \resetmathattributes\Uchar#1%
@@ -196,7 +196,7 @@
% \fi
% \endgroup}
-\unexpanded\def\rawmathematics#1% slow but only for tracing
+\permanent\protected\def\rawmathematics#1% slow but only for tracing
{\begingroup
\ifmmode
\clf_resetmathattributes#1%
@@ -221,22 +221,22 @@
\installswitchcommandhandler \??mathematics {mathematics} \??mathematics
-\unexpanded\def\startmathematics % no grouping, if ever then also an optional second
+\permanent\protected\def\startmathematics % no grouping, if ever then also an optional second
{\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop}
\installmacrostack\currentmathematics
-\unexpanded\def\math_mathematics_start_yes[#1]%
+\protected\def\math_mathematics_start_yes[#1]%
{\push_macro_currentmathematics
\edef\currentmathematics{#1}% check for valid
\the\everyswitchmathematics}
-\unexpanded\def\math_mathematics_start_nop
+\protected\def\math_mathematics_start_nop
{\push_macro_currentmathematics
\let\currentmathematics\empty
\the\everyswitchmathematics}
-\unexpanded\def\stopmathematics
+\permanent\protected\def\stopmathematics
{\pop_macro_currentmathematics
\the\everyswitchmathematics}
@@ -244,7 +244,7 @@
% Now we redefine \type {\mathematics} and \type {\m}:
-\unexpanded\def\mathematics
+\permanent\protected\def\mathematics
{\doifelsenextoptionalcs\math_m_yes\math_m_nop}
\def\math_m_yes
@@ -258,18 +258,6 @@
\def\math_m_yes_math[#1]#2%
{#2}
-% \def\math_m_yes_text[#1]%
-% {\begingroup
-% \doifassignmentelse{#1}%
-% {\setupcurrentmathematics[#1]}%
-% {\edef\currentmathematics{#1}}% check for valid
-% \edef\p_openup{\mathematicsparameter\c!openup}%
-% \ifx\p_openup\v!yes
-% \expandafter\math_m_yes_text_openedup
-% \else
-% \expandafter\math_m_yes_text_normal
-% \fi}
-
\def\math_m_yes_text[#1]%
{\begingroup
\ifcondition\validassignment{#1}%
@@ -418,21 +406,21 @@
% todo: only in mmode
% these commands are semi-public but should not be used directly (lua names wil change)
-\unexpanded\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
-\unexpanded\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi}
-\unexpanded\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi}
-\unexpanded\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi}
+\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}
\installcorenamespace{mathstylealternative} % might become a setuphandler
-\unexpanded\def\math_set_font_style_alternate#1%
+\protected\def\math_set_font_style_alternate#1%
{\ifcsname\??mathstylealternative\fontclass:#1\endcsname
\expandafter\math_set_font_alternate\lastnamedcs
\orelse\ifcsname\??mathstylealternative#1\endcsname
\expandafter\math_set_font_alternate\lastnamedcs
\fi}
-\unexpanded\def\setupmathrendering % the name might change
+\protected\def\setupmathrendering % the name might change
{\dodoubleargument\math_setup_rendering}
\def\math_setup_rendering[#1][#2]%
@@ -462,24 +450,31 @@
% \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$
% \stopTEXpage
-\unexpanded\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file
-\unexpanded\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file
-\unexpanded\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic
-\unexpanded\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic
-\unexpanded\def\mathdotlessi {\begingroup\mathdotless i\endgroup}
-\unexpanded\def\mathdotlessj {\begingroup\mathdotless j\endgroup}
+% no longer needed now we have enforce so the next few lines will go
+
+\pushoverloadmode
+ \enforced\let\dotlessi\dotlessi
+ \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\mathdotlessi {\begingroup\mathdotless i\endgroup}
+\permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup}
-\let\mathaltcal\mathaltcalligraphic
-\let\mathaltit \mathaltitalic
+\aliased\let\mathaltcal\mathaltcalligraphic
+\aliased\let\mathaltit \mathaltitalic
-%let\textslashedzero\slashedzero \unexpanded\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero}
-\let\textdotlessi \dotlessi \unexpanded\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi}
-\let\textdotlessj \dotlessj \unexpanded\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj}
+%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero}
+\aliased\let\textdotlessi \dotlessi \permanent\protected\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi}
+\aliased\let\textdotlessj \dotlessj \permanent\protected\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj}
\appendtoks
- %let\slashedzero\autoslashedzero
- \let\dotlessi \autodotlessi
- \let\dotlessj \autodotlessj
+ %enforced\let\slashedzero\autoslashedzero
+ \enforced\let\dotlessi\autodotlessi
+ \enforced\let\dotlessj\autodotlessj
\to \everymathematics
\let\setmathattribute \math_set_attribute
@@ -492,72 +487,72 @@
\let\mathalternate \math_set_font_alternate
-\unexpanded\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf}
-\unexpanded\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it}
-\unexpanded\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script}
-\unexpanded\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur}
-\unexpanded\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\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}
-\unexpanded\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf}
-\unexpanded\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf}
-\unexpanded\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\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}
-\unexpanded\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf}
-\unexpanded\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl
-\unexpanded\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\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}
-\unexpanded\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf}
-\unexpanded\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl
-\unexpanded\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\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
\appendtoks
\edef\p_default{\mathematicsparameter\c!default}%
\ifx\p_default\v!normal
- \let\mathdefault\mathupright
+ \enforced\let\mathdefault\mathupright
\else
- \let\mathdefault\mathitalic
+ \enforced\let\mathdefault\mathitalic
\fi
\to \everysetupmathematics
\setupmathematics
[\c!default=\v!italic]
-\let\tfmath\mathtf % maybe a grouped command
-\let\slmath\mathsl
-\let\itmath\mathit
+\aliased\let\tfmath\mathtf % maybe a grouped command
+\aliased\let\slmath\mathsl
+\aliased\let\itmath\mathit
-\let\bfmath\mathbf
-\let\bsmath\mathbs
-\let\bimath\mathbi
+\aliased\let\bfmath\mathbf
+\aliased\let\bsmath\mathbs
+\aliased\let\bimath\mathbi
-\let\Bbb\mathblackboard
+\aliased\let\Bbb\mathblackboard
-\unexpanded\def\frak {\ifmmode\expandafter\mathfraktur \fi}
-\unexpanded\def\cal {\ifmmode\expandafter\mathscript \fi}
-\unexpanded\def\bbd {\ifmmode\expandafter\mathblackboard\fi}
-\unexpanded\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
-\unexpanded\def\fraktur {\ifmmode\expandafter\mathfraktur \fi}
-\unexpanded\def\gothic {\ifmmode\expandafter\mathfraktur \fi}
+\permanent\protected\def\frak {\ifmmode\expandafter\mathfraktur \fi}
+\permanent\protected\def\cal {\ifmmode\expandafter\mathscript \fi}
+\permanent\protected\def\bbd {\ifmmode\expandafter\mathblackboard\fi}
+\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
+\permanent\protected\def\fraktur {\ifmmode\expandafter\mathfraktur \fi}
+\permanent\protected\def\gothic {\ifmmode\expandafter\mathfraktur \fi}
-\unexpanded\def\mathcal #1{{\mathscript #1}} % for AMS compatibility
-\unexpanded\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility
-\unexpanded\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility
+\permanent\protected\def\mathcal #1{{\mathscript #1}} % for AMS compatibility
+\permanent\protected\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility
+\permanent\protected\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility
-\ifdefined\normaltf\else\let\normaltf\tf\fi \unexpanded\def\tf{\ifmmode\mathtf\else\normaltf\fi}
-\ifdefined\normalbf\else\let\normalbf\bf\fi \unexpanded\def\bf{\ifmmode\mathbf\else\normalbf\fi}
-\ifdefined\normalit\else\let\normalit\it\fi \unexpanded\def\it{\ifmmode\mathit\else\normalit\fi}
-\ifdefined\normalsl\else\let\normalsl\sl\fi \unexpanded\def\sl{\ifmmode\mathsl\else\normalsl\fi}
-\ifdefined\normalbi\else\let\normalbi\bi\fi \unexpanded\def\bi{\ifmmode\mathbi\else\normalbi\fi}
-\ifdefined\normalbs\else\let\normalbs\bs\fi \unexpanded\def\bs{\ifmmode\mathbs\else\normalbs\fi}
+\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\mathtf\else\normaltf\fi}
+\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\mathbf\else\normalbf\fi}
+\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\mathit\else\normalit\fi}
+\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\mathsl\else\normalsl\fi}
+\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\mathbi\else\normalbi\fi}
+\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\mathbs\else\normalbs\fi}
-\unexpanded\def\rm{\ifmmode\mathrm\else\normalrm\fi}
-\unexpanded\def\ss{\ifmmode\mathss\else\normalss\fi}
-\unexpanded\def\tt{\ifmmode\mathtt\else\normaltt\fi}
+\permanent\protected\def\rm{\ifmmode\mathrm\else\normalrm\fi}
+\permanent\protected\def\ss{\ifmmode\mathss\else\normalss\fi}
+\permanent\protected\def\tt{\ifmmode\mathtt\else\normaltt\fi}
-\ifdefined\mr \else \let\mr\relax \fi
-\ifdefined\mb \else \let\mb\relax \fi
+\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent
+\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent
% 1: $\setmathattribute{ss}{bf}3$
% 2: $\setmathattribute{ss}{bf}\setmathfontstylealternate{bf}3$
@@ -608,39 +603,39 @@
\let\mathboldsymbol\relax % yet unsupported, will be
-\unexpanded\def\boldsymbol
+\permanent\protected\def\boldsymbol
{\mathortext\mathboldsymbol\bold}
%D Helpers
-\def\utfmathclass #1{\clf_utfmathclass {#1}}
-\def\utfmathstretch#1{\clf_utfmathstretch{#1}}
-\def\utfmathcommand#1{\clf_utfmathcommand{#1}}
-\def\utfmathfiller #1{\clf_utfmathfiller {#1}}
+\permanent\def\utfmathclass #1{\clf_utfmathclass {#1}}
+\permanent\def\utfmathstretch#1{\clf_utfmathstretch{#1}}
+\permanent\def\utfmathcommand#1{\clf_utfmathcommand{#1}}
+\permanent\def\utfmathfiller #1{\clf_utfmathfiller {#1}}
-\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}}
-\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}}
-\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}}
+\permanent\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}}
+\permanent\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}}
+\permanent\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}}
-\unexpanded\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}}
-\unexpanded\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}}
-\unexpanded\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}}
-\unexpanded\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}}
-\unexpanded\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}}
+\permanent\protected\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}}
+\permanent\protected\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}}
+\permanent\protected\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}}
+\permanent\protected\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}}
+\permanent\protected\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}}
-\let\doifutfmathaccentelse \doifelseutfmathaccent
-\let\doifutfmathaboveelse \doifelseutfmathabove
-\let\doifutfmathbelowelse \doifelseutfmathbelow
-\let\doifutfmathfillerelse \doifelseutfmathfiller
-\let\doifutfmathlimopelse \doifelseutfmathlimop
+\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent
+\aliased\let\doifutfmathaboveelse \doifelseutfmathabove
+\aliased\let\doifutfmathbelowelse \doifelseutfmathbelow
+\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller
+\aliased\let\doifutfmathlimopelse \doifelseutfmathlimop
%D Not used that much:
\installcorenamespace{mathcodecommand}
-\unexpanded\def\mathlimop#1{\mathop{#1}} %no \limits
-\unexpanded\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
-\unexpanded\def\mathnolop#1{\mathop{#1}\nolimits}
+\permanent\protected\def\mathlimop#1{\mathop{#1}} %no \limits
+\permanent\protected\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
+\permanent\protected\def\mathnolop#1{\mathop{#1}\nolimits}
\let\mathnothing\firstofoneunexpanded
\let\mathalpha \firstofoneunexpanded
@@ -663,9 +658,9 @@
\setnewconstant\mathaccentcode \pluseight
\setnewconstant\mathradicalcode \plusnine
- \def\mathcodenumber #1{\the\csname math#1code\endcsname}
-\unexpanded\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}
- \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi}
+\permanent \def\mathcodenumber #1{\the\csname math#1code\endcsname}
+\permanent\protected\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}
+\permanent \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi}
% \startlines
% $\mathopnolimits{\rm d}x$
@@ -681,11 +676,10 @@
\installcorenamespace{mathcommand}
-\unexpanded\def\definemathcommand
- {\dotripleempty\math_define_command}
+% todo: define these commands as frozen!
-\def\math_define_command[#1][#2][#3]#4% command class args meaning
- {\ifthirdargument
+\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning
+ {\ifparameter#3\or
\edef\nofmathcommandarguments{#3}%
\ifx\nofmathcommandarguments\v!one
\setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}%
@@ -694,14 +688,16 @@
\else
\setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
\fi
- \orelse\ifsecondargument
+ \orelse\ifparameter#2\or
\setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
\else
\setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}%
\fi
- \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname}
+ \ifparameter#1\or % safeguard
+ \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname
+ \fi}
-\unexpanded\def\mathcommand#1%
+\permanent\protected\def\mathcommand#1%
{\begincsname\??mathcommand#1\endcsname}
%D Let's define a few comands here:
@@ -712,17 +708,17 @@
\chardef\c_math_strut"28
-\unexpanded\def\math_strut_htdp#1%
+\protected\def\math_strut_htdp#1%
{\s!height\fontcharht#1\c_math_strut
\s!depth \fontchardp#1\c_math_strut}
-\unexpanded\def\math_strut_normal
+\protected\def\math_strut_normal
{\vrule
\s!width \zeropoint
\normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
\relax}
-\unexpanded\def\math_strut_visual
+\protected\def\math_strut_visual
{\hskip-.01\emwidth
\vrule
\s!width .02\emwidth
@@ -730,19 +726,23 @@
\relax
\hskip-.01\emwidth}
-\unexpanded\def\showmathstruts % let's not overload \math_strut_normal
- {\let\math_strut\math_strut_visual}
+\protected\def\showmathstruts % let's not overload \math_strut_normal
+ {\enforced\let\math_strut\math_strut_visual}
\let\math_strut\math_strut_normal
-% \unexpanded\def\mathstrut{\mathcodecommand{nothing}{\math_strut}}
+% \protected\def\mathstrut{\mathcodecommand{nothing}{\math_strut}}
+
+\pushoverloadmode
+
+ \definemathcommand [mathstrut] {\math_strut}
-\definemathcommand [mathstrut] {\math_strut}
+\popoverloadmode
%D We could have a arg variant \unknown\ but not now.
-\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
-\unexpanded\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
+\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
+\permanent\protected\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
%D Moved from font-ini.mkiv:
%D
@@ -751,14 +751,13 @@
%D
%D Todo:
-\unexpanded\def\mf
- {\begincsname\fontalternative\endcsname}
+\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen
% \let\normalmathop\mathop % already defined
% no longer needed as we no longer switch fonts
%
-% \unexpanded\def\mathop
+% \protected\def\mathop
% {\normalmathop
% \bgroup
% % no: \let\rm\mf
@@ -768,7 +767,7 @@
% this one too: \letvalue{\??mathcodecommand op}\mathop ?
-\unexpanded\def\normalmbox
+\permanent\protected\def\normalmbox
{\normalhbox\bgroup
\usemathematicsstyleandcolor\c!textstyle\c!textcolor % new
\dowithnextboxcs\math_mbox_finish\normalhbox}
@@ -777,16 +776,16 @@
{\flushnextbox
\egroup}
-\unexpanded\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
+\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
{\ifmmode\normalmbox\else\normalhbox\fi}
-\unexpanded\def\enablembox
+\permanent\protected\def\enablembox
{\toksapp\everymathematics{\math_enable_mbox}}
-\def\math_enable_mbox
- {\let\hbox\mbox}
+\permanent\def\math_enable_mbox % brrrr
+ {\enforced\let\hbox\mbox}
-\unexpanded\def\snappedmath#1% sort of \struttedbox
+\permanent\protected\def\snappedmath#1% sort of \struttedbox
{\dontleavehmode
\begingroup
\setbox\scratchbox\normalhbox\bgroup
@@ -797,7 +796,7 @@
\box\scratchbox
\endgroup}
-\unexpanded\def\mtext#1%
+\permanent\protected\def\mtext#1%
{\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}}
%D The next hack is needed needed for sine, cosine etc.
@@ -810,8 +809,8 @@
\let\math_tags_mo\firstofoneunexpanded
\let\math_tags_mi\firstofoneunexpanded
-\unexpanded\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup}
-\unexpanded\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup}
+\protected\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup}
+\protected\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup}
% Once this is stable we can store the number at the tex end which is
% faster. Functions getnumbers >= 1000.
@@ -824,7 +823,7 @@
\c!functionstyle=, % rm ss etc i.e. known alternatives, otherwise math
\c!functioncolor=]
-\unexpanded\def\math_mfunction_styled
+\protected\def\math_mfunction_styled
{\begingroup
\usemathematicscolorparameter\c!functioncolor
\edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
@@ -836,28 +835,28 @@
\doubleexpandafter\math_mfunction_styled_math
\fi}
-\unexpanded\def\math_mfunction_styled_text#1%
+\protected\def\math_mfunction_styled_text#1%
%{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}%
{\expandafter\mathoptext\expandafter{\lastnamedcs#1}%
\endgroup}
-\unexpanded\def\math_mfunction_styled_math#1%
+\protected\def\math_mfunction_styled_math#1%
{\p_functionstyle
#1%
\endgroup}
-\unexpanded\def\math_mfunction_styled_none#1%
+\protected\def\math_mfunction_styled_none#1%
{\mathupright
#1%
\endgroup}
-\unexpanded\def\mfunction#1%
+\permanent\protected\def\mfunction#1%
{\begingroup
\math_tags_mfunctiontxt{#1}\c_apply_function
\math_mfunction_styled{#1}%
\endgroup}
-\unexpanded\def\mfunctionlabeltext#1%
+\permanent\protected\def\mfunctionlabeltext#1%
{\begingroup
\math_tags_mfunctionlab{#1}\c_apply_function
\math_mfunction_styled{\mathlabeltext{#1}}%
@@ -866,14 +865,14 @@
\let\math_tags_mfunctiontxt\gobbletwoarguments
\let\math_tags_mfunctionlab\gobbletwoarguments
-\unexpanded\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup}
-\unexpanded\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup}
-\unexpanded\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup}
-\unexpanded\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext
+\permanent\protected\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup}
+\permanent\protected\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup}
+\permanent\protected\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup}
+\permanent\protected\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext
\newconditional\c_apply_function
-\unexpanded\def\math_tags_apply#1#2%
+\permanent\protected\def\math_tags_apply#1#2%
{\begingroup
\settrue\c_apply_function
#1%
@@ -884,20 +883,20 @@
\endgroup}
\appendtoks
- \let\math_tags_mfunctiontxt\clf_tagmfunctiontxt
- \let\math_tags_mfunctionlab\clf_tagmfunctionlab
- \let\math_tags_mo \math_tags_mo_indeed
- \let\math_tags_mi \math_tags_mi_indeed
- \let\math_tags_mn \math_tags_mn_indeed
- \let\math_tags_ms \math_tags_ms_indeed
+ \enforced\let\math_tags_mfunctiontxt\clf_tagmfunctiontxt
+ \enforced\let\math_tags_mfunctionlab\clf_tagmfunctionlab
+ \enforced\let\math_tags_mo \math_tags_mo_indeed
+ \enforced\let\math_tags_mi \math_tags_mi_indeed
+ \enforced\let\math_tags_mn \math_tags_mn_indeed
+ \enforced\let\math_tags_ms \math_tags_ms_indeed
\to \everyenableelements
\appendtoks
- \let\mo \math_tags_mo
- \let\mi \math_tags_mi
- \let\mn \math_tags_mn
- \let\ms \math_tags_ms
- \let\apply\math_tags_apply
+ \enforced\let\mo \math_tags_mo
+ \enforced\let\mi \math_tags_mi
+ \enforced\let\mn \math_tags_mn
+ \enforced\let\ms \math_tags_ms
+ \enforced\let\apply\math_tags_apply
\to\everymathematics
% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}}
@@ -908,11 +907,11 @@
%
% \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
%
-% \unexpanded\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits}
-% \unexpanded\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}}
-% \unexpanded\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}}
+% \protected\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits}
+% \protected\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}}
+% \protected\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}}
%
-% \unexpanded\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
+% \protected\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
% {\doifsomething{#1}
% {\def\currentmscaledstyle{#1}%
% \let\mathopnolimits \math_function_style_opnolimits
@@ -921,14 +920,14 @@
\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
-\unexpanded\def\mscaledtext#1%
+\permanent\protected\def\mscaledtext#1%
{\mathchoice
{\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
{\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
{\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
{\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}
-\unexpanded\def\setmathfunctionstyle#1%
+\permanent\protected\def\setmathfunctionstyle#1%
{\setupmathematics[\c!functionstyle=#1]} % for old times sake
%D Usage:
@@ -965,12 +964,12 @@
\newtoks\activatedmathcharacters
-\unexpanded\def\activatemathcharacter#1%
+\permanent\protected\def\activatemathcharacter#1%
{\appendtoks
\global\mathcode#1=\activemathcharcode
\to \activatedmathcharacters}
-\def\activatemathcharacters
+\permanent\def\activatemathcharacters
{\the\activatedmathcharacters}
% beware, not runtime, so has to happen at format generation
@@ -1121,7 +1120,7 @@
% \let\prime\math_prime_indeed % so this is needed
% \to \everydump
%
-% \unexpanded\def\math_prime_indeed
+% \protected\def\math_prime_indeed
% {\iffontchar\textfont\zerocount"FE325\relax
% ^\bgroup
% \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal)
@@ -1167,7 +1166,7 @@
% $\char26$ gives an error because it expands to an active character that
% then becomes an & which is then seen as an alignment character; anyway,
-% even when we switch like this the diufferen tmeaning only happens when
+% even when we switch like this the different meaning only happens when
% we're in math mode which can be delayed till we're in a cell
\bgroup
@@ -1178,19 +1177,19 @@
\glet\specialmathaligntab\normalmathaligntab
- \unexpanded\gdef\obeymathcatcodes
+ \permanent\protected\gdef\obeymathcatcodes
{\let _\normalsubscript
\let ^\normalsuperscript
\def &\specialmathaligntab
}
- \doglobal \appendtoks
- \let _\normalsubscript
- \let ^\normalsuperscript
- \let &\specialmathaligntab
- \to \everymathematics
+ \doglobal\appendtoks
+ \enforced\let _\normalsubscript
+ \enforced\let ^\normalsuperscript
+ \enforced\let &\specialmathaligntab
+ \to \everymathematics
- % \unexpanded\gdef\normalmathampersands
+ % \permanent\protected\gdef\normalmathampersands
% {\let\specialmathaligntab\mathampersand}
\egroup
@@ -1262,43 +1261,43 @@
%D Even more drastic (this code will move as nonknuthmode is default now)
-% \unexpanded\def\enableasciimode
+% \protected\def\enableasciimode
% {\ctxlua{resolvers.macros.enablecomment()}%
% \glet\enableasciimode\relax}
%
-% \unexpanded\def\asciimode
+% \protected\def\asciimode
% {\catcodetable\txtcatcodes
% \enableasciimode
% \nonknuthmode}
%
-% \unexpanded\def\startasciimode
+% \protected\def\startasciimode
% {\pushcatcodetable
% \catcodetable\txtcatcodes
% \enableasciimode
% \nonknuthmode}
%
-% \unexpanded\def\stopasciimode
+% \protected\def\stopasciimode
% {\popcatcodetable
% \ifconditional\knuthmode\else\donknuthmode\fi}
-\unexpanded\def\enableasciimode
+\permanent\protected\def\enableasciimode
{\clf_enableasciimode} % relaxes itself
-\unexpanded\def\asciimode
+\permanent\protected\def\asciimode
{\catcodetable\txtcatcodes
\clf_enableasciimode}
-\unexpanded\def\startasciimode
+\permanent\protected\def\startasciimode
{\pushcatcodetable
\catcodetable\txtcatcodes
\clf_enableasciimode}
-\unexpanded\def\stopasciimode
+\permanent\protected\def\stopasciimode
{\popcatcodetable}
%D Needed for unicode:
-\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}
+\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}
%D Memory saver:
@@ -1361,7 +1360,7 @@
\fi
\to \everyswitchmathematics
-\unexpanded\def\math_basics_synchronize_direction
+\protected\def\math_basics_synchronize_direction
{\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi}
% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode
@@ -1444,9 +1443,9 @@
% only used local
-\unexpanded\def\mathgreekupright{\c_attr_mathgreek"222\relax}
-\unexpanded\def\mathgreekitalic {\c_attr_mathgreek"333\relax}
-\unexpanded\def\mathgreekdefault{\c_attr_mathgreek"000\relax}
+\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax}
+\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax}
+\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax}
\let\mathgreeknormal\mathgreekupright
\let\mathgreeknone \mathgreekdefault
@@ -1581,8 +1580,8 @@
% \newconditional\automathpunctuation
%
-% \unexpanded\def\enablemathpunctuation {\settrue \automathpunctuation}
-% \unexpanded\def\disablemathpunctuation{\setfalse\automathpunctuation}
+% \protected\def\enablemathpunctuation {\settrue \automathpunctuation}
+% \protected\def\disablemathpunctuation{\setfalse\automathpunctuation}
%
% \appendtoks
% \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
@@ -1593,8 +1592,8 @@
%
% \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi}
%
-% \unexpanded\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
-% \unexpanded\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
+% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
+% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
%
% \setnewconstant\c_math_comma "002C
% \setnewconstant\c_math_period "002E
@@ -1605,17 +1604,17 @@
% \catcode\c_math_comma \activecatcode
% \catcode\c_math_period\activecatcode
%
-% \unexpanded\gdef\math_punctuation_initialize_indeed
+% \protected\gdef\math_punctuation_initialize_indeed
% {\mathcode\c_math_comma \c_math_special
% \mathcode\c_math_period\c_math_special
% \let,\math_punctuation_comma
% \let.\math_punctuation_period
% \c_attr_mathpunctuation\plustwo}
%
-% \unexpanded\gdef\math_punctuation_initialize_yes
+% \protected\gdef\math_punctuation_initialize_yes
% {\c_attr_mathpunctuation\plustwo}
%
-% \unexpanded\gdef\math_punctuation_initialize_nop
+% \protected\gdef\math_punctuation_initialize_nop
% {\c_attr_mathpunctuation\plusone}
%
% \egroup
@@ -1636,11 +1635,11 @@
% \def\math_punctuation_comma_next {\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textcomma }}
% \def\math_punctuation_period_next{\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textperiod}}
%
-% \unexpanded\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
-% \unexpanded\def\math_punctuation_nop_period{\mathord{\textperiod}}
+% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
+% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}}
%
-% \unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
-% \unexpanded\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
+% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
+% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
%
% \let\math_punctuation_yes_comma \math_punctuation_all_comma
% \let\math_punctuation_yes_period\math_punctuation_nop_period
@@ -1665,19 +1664,19 @@
\edef\math_set_o_both {\math_set_o_period\math_set_o_comma}
\edef\math_set_p_both {\math_set_p_period\math_set_p_comma}
-\unexpanded\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup}
-\unexpanded\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup}
-\unexpanded\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup}
+\protected\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup}
+\protected\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup}
+\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup}
% todo: use new lookahead stuff
-\unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
-\unexpanded\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next}
-\unexpanded\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next}
+\protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
+\protected\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next}
+\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next}
- \let\math_punctuation_yes_comma \math_punctuation_all_comma
- \let\math_punctuation_yes_period \math_punctuation_nop_period
- \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon
+ \let\math_punctuation_yes_comma \math_punctuation_all_comma
+ \let\math_punctuation_yes_period \math_punctuation_nop_period
+ \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon
\def\math_punctuation_comma_next {\begingroup\Umathcode\c_math_comma \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_comma ,\endgroup}
\def\math_punctuation_period_next {\begingroup\Umathcode\c_math_period \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_period .\endgroup}
@@ -1815,7 +1814,7 @@
% 6 = scriptscript
% 7 = crampedscriptscript
-\def\uncramped#1%
+\permanent\def\uncramped#1%
{{\ifmathstyle
\or \displaystyle \or
\or \textstyle \or
@@ -1823,7 +1822,7 @@
\or \scriptscriptstyle \fi
#1}}
-\def\cramped#1%
+\permanent\def\cramped#1%
{{\ifmathstyle
\crampeddisplaystyle \or \or % 0 -> 1
\crampedtextstyle \or \or % 2 -> 3
@@ -1831,11 +1830,11 @@
\crampedscriptscriptstyle \fi % 6 -> 7
#1}}
-\def\triggermathstyle#1{\Ustyle\numexpr#1\relax}
-%def\mathstyletrigger#1{\numexpr#1\relax}
-\let\mathstyletrigger \firstofoneargument
+\permanent\def\triggermathstyle#1{\Ustyle\numexpr#1\relax}
+%permanent\def\mathstyletrigger#1{\numexpr#1\relax}
+\permanent\let\mathstyletrigger \firstofoneargument
-\def\triggeredmathstyleparameter#1% to bypass the relax
+\permanent\def\triggeredmathstyleparameter#1% to bypass the relax
{\ifcase\numexpr\normalmathstyle\relax
#1\displaystyle \or % 0
#1\crampeddisplaystyle \or % 1
@@ -1848,7 +1847,7 @@
% error
\fi}
-\def\mathstylefont#1% #1 is number (\normalmathstyle)
+\permanent\def\mathstylefont#1% #1 is number (\normalmathstyle)
{\ifcase\numexpr#1\relax
\textfont \or
\textfont \or
@@ -1861,7 +1860,7 @@
\textfont
\fi\fam} % was \zerocount
-\def\somemathstylefont#1% #1 is number (\normalmathstyle)
+\permanent\def\somemathstylefont#1% #1 is number (\normalmathstyle)
{\ifcase\numexpr#1\relax
\textfont \or
\textfont \or
@@ -1874,7 +1873,7 @@
\textfont
\fi}
-\def\mathsmallstylefont#1% #1 is number (\normalmathstyle)
+\permanent\def\mathsmallstylefont#1% #1 is number (\normalmathstyle)
{\ifcase\numexpr#1\relax
\scriptfont \or
\scriptfont \or
@@ -1887,7 +1886,7 @@
\scriptfont
\fi\fam} % was \zerocount
-\def\mathstyleface#1% #1 is number (\normalmathstyle)
+\permanent\def\mathstyleface#1% #1 is number (\normalmathstyle)
{\ifcase\numexpr#1\relax
\textface \or
\textface \or
@@ -1900,7 +1899,7 @@
\textface
\fi}
-\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
+\permanent\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
{\ifcase\numexpr#1\relax
\scriptface \or
\scriptface \or
@@ -1913,7 +1912,7 @@
\scriptface
\fi}
-\def\mathstylecommand#1#2#3%
+\permanent\def\mathstylecommand#1#2#3%
{\ifcase\numexpr\normalmathstyle\relax
\expandafter#1\or
\expandafter#1\or
@@ -1925,7 +1924,7 @@
\expandafter#3\else
\expandafter#1\fi}
-% \def\textstyleface#1% #1 is number (\normalmathstyle)
+% \permanent\def\textstyleface#1% #1 is number (\normalmathstyle)
% {\ifcase\numexpr#1\relax
% \tf \or
% \tf \or
@@ -1938,7 +1937,7 @@
% \tf
% \fi}
-\unexpanded\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
+\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
{{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax
display\or % 0
crampeddisplay\or % 1
@@ -1950,13 +1949,13 @@
crampedscriptscript\else % 7
unknown\fi]}}}
-\unexpanded\def\showmathstyle{\verbosemathstyle\normalmathstyle}
+\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle}
%D Handy too:
-\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle}
-\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle}
-\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle}
+\permanent\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle}
+\permanent\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle}
+\permanent\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle}
%D Some dimension fun:
@@ -1965,7 +1964,7 @@
%D A plain inheritance:
-\def\mathpalette#1#2%
+\permanent\def\mathpalette#1#2%
{\mathchoice
{#1\displaystyle {#2}}%
{#1\textstyle {#2}}%
@@ -1982,40 +1981,40 @@
% to be tested: {#1} but it could have side effects
-% \unexpanded\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b}
+% \protected\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b}
% {\normalexpanded{\hbox\bgroup
% \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
-\unexpanded\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b}
+\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b}
{\math_style_hbox{#1}}
-\unexpanded\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b}
+\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b}
{\normalexpanded{\hbox#1\bgroup
\startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup}
-\unexpanded\def\mathstylevbox#1%
+\permanent\protected\def\mathstylevbox#1%
{\normalexpanded{\vbox\bgroup
\startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
-\unexpanded\def\mathstylevcenter#1%
+\permanent\protected\def\mathstylevcenter#1%
{\normalexpanded{\vcenter\bgroup
\startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
-\unexpanded\def\mathstylevcenteredhbox#1%
+\permanent\protected\def\mathstylevcenteredhbox#1%
{\normalexpanded{\vcenter\bgroup\hbox\bgroup
\startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
-\unexpanded\def\mathstylevcenteredvbox#1%
+\permanent\protected\def\mathstylevcenteredvbox#1%
{\normalexpanded{\vcenter\bgroup\vbox\bgroup
\startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
-\unexpanded\def\setmathsmalltextbox#1#2#%
+\permanent\protected\def\setmathsmalltextbox#1#2#%
{\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}%
\setbox#1#2\bgroup
\font_basics_switchtobodyfont\m_math_text_choice_face
\let\next}
-\unexpanded\def\setmathtextbox#1#2#%
+\permanent\protected\def\setmathtextbox#1#2#%
{\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
\setbox#1#2\bgroup
\font_basics_switchtobodyfont\m_math_text_choice_face
@@ -2042,7 +2041,7 @@
%D \HL
%D \stoptabulate
-\def\triggerdisplaystyle
+\permanent\def\triggerdisplaystyle
{\ifmathstyle
\displaystyle \or
\crampeddisplaystyle \or
@@ -2054,7 +2053,7 @@
\crampeddisplaystyle \or
\fi}
-\def\triggertextstyle
+\permanent\def\triggertextstyle
{\ifmathstyle
\textstyle \or
\crampedtextstyle \or
@@ -2066,7 +2065,7 @@
\crampedtextstyle \else
\fi}
-\def\triggerscriptstyle
+\permanent\def\triggerscriptstyle
{\ifmathstyle
\scriptstyle \or
\crampedscriptstyle \or
@@ -2078,7 +2077,7 @@
\crampedscriptstyle \or
\fi}
-\def\triggerscriptscriptstyle
+\permanent\def\triggerscriptscriptstyle
{\ifmathstyle
\scriptscriptstyle \or
\crampedscriptscriptstyle \or
@@ -2090,21 +2089,21 @@
\crampedscriptscriptstyle \or
\fi}
-\def\triggeruncrampedstyle
+\permanent\def\triggeruncrampedstyle
{\ifmathstyle
\or \displaystyle \or
\or \textstyle \or
\or \scriptstyle \or
\or \scriptscriptstyle \fi}
-\def\triggercrampedstyle
+\permanent\def\triggercrampedstyle
{\ifmathstyle
\crampeddisplaystyle \or \or
\crampedtextstyle \or \or
\crampedscriptstyle \or \or
\crampedscriptscriptstyle \fi}
-\def\triggersmallstyle
+\permanent\def\triggersmallstyle
{\ifmathstyle
\scriptstyle \or
\crampedscriptstyle \or
@@ -2116,7 +2115,7 @@
\crampedscriptscriptstyle \or
\fi}
-\def\triggeruncrampedsmallstyle
+\permanent\def\triggeruncrampedsmallstyle
{\ifmathstyle
\scriptstyle \or
\scriptstyle \or
@@ -2128,7 +2127,7 @@
\scriptscriptstyle \or
\fi}
-\def\triggercrampedsmallstyle
+\permanent\def\triggercrampedsmallstyle
{\ifmathstyle
\crampedscriptstyle \or
\crampedscriptstyle \or
@@ -2140,7 +2139,7 @@
\crampedscriptscriptstyle \or
\fi}
-\def\triggerbigstyle
+\permanent\def\triggerbigstyle
{\ifmathstyle
\displaystyle \or
\crampeddisplaystyle \or
@@ -2152,7 +2151,7 @@
\crampedscriptstyle \or
\fi}
-\def\triggeruncrampedbigstyle
+\permanent\def\triggeruncrampedbigstyle
{\ifmathstyle
\displaystyle \or
\displaystyle \or
@@ -2164,7 +2163,7 @@
\scriptstyle \or
\fi}
-\def\triggercrampedbigstyle
+\permanent\def\triggercrampedbigstyle
{\ifmathstyle
\crampeddisplaystyle \or
\crampeddisplaystyle \or
@@ -2178,10 +2177,10 @@
\newcount\c_math_saved_style
-\unexpanded\def\pushmathstyle % assumes begingroup .. endgroup
+\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup
{\c_math_saved_style\mathstyle}
-\unexpanded\def\popmathstyle
+\permanent\protected\def\popmathstyle
{\ifnum\mathstyle=\c_math_saved_style\else
\triggermathstyle\c_math_saved_style
\fi}
@@ -2266,7 +2265,7 @@
\fi
}
-\unexpanded\def\math_style_set#1%
+\protected\def\math_style_set#1%
{\edef\m_math_style_asked{#1}%
\ifempty\m_math_style_asked \else
\math_style_set_indeed
@@ -2274,7 +2273,7 @@
\let\setmathstyle\math_style_set
-\def\installmathstyle#1#2%
+\permanent\def\installmathstyle#1#2%
{\ifcsname\??mathstylecommand#1\endcsname \else
\setvalue{\??mathstylecommand#1}{#2}%
\fi}
@@ -2295,13 +2294,13 @@
\setvalue{\??mathstylecommand\v!small }{\c_math_styles_state_size \plusone}
\setvalue{\??mathstylecommand\v!big }{\c_math_styles_state_size \plustwo}
-\unexpanded\def\setupmathstyle[#1]%
+\permanent\protected\def\setupmathstyle[#1]%
{\edef\m_math_style_asked{#1}%
\ifempty\m_math_style_asked \else
\math_style_set_indeed
\fi}
-\unexpanded\def\usemathstyleparameter#1% faster local variant
+\permanent\protected\def\usemathstyleparameter#1% faster local variant
{\edef\m_math_style_asked{#1\c!mathstyle}%
\ifempty\m_math_style_asked \else
\math_style_set_indeed
@@ -2317,10 +2316,7 @@
\installcorenamespace {mathstyle}
-\unexpanded\def\definemathstyle
- {\dodoubleargument\math_style_define}
-
-\def\math_style_define[#1][#2]%
+\permanent\tolerant\protected\def\definemathstyle[#1]#*[#2]%
{\c_math_styles_state_style \zerocount
\c_math_styles_state_cramped\zerocount
\c_math_styles_state_size \zerocount
@@ -2386,7 +2382,7 @@
%D
%D \typebuffer \getbuffer
-\unexpanded\def\startmathstyle[#1]%
+\permanent\protected\def\startmathstyle[#1]%
{\edef\m_math_style_asked{#1}%
\ifempty\m_math_style_asked
\let\stopmathstyle\relax
@@ -2398,7 +2394,7 @@
\let\stopmathstyle\relax
-\unexpanded\def\startusemathstyleparameter#1%
+\permanent\protected\def\startusemathstyleparameter#1%
{\edef\m_math_style_asked{#1\c!mathstyle}%
\ifempty\m_math_style_asked
\let\stopusemathstyleparameter\relax
@@ -2482,32 +2478,34 @@
%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
\mathrulethicknessmode\plusone % adaptive
-\unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox}
-\unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox}
+\permanent\protected\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox}
+\permanent\protected\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox}
-\unexpanded\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
-\unexpanded\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
-\unexpanded\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
-\unexpanded\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
-\unexpanded\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
-\unexpanded\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
+\permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
+\permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
+\permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
+\permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
+\permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
+\permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
-\unexpanded\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
-\unexpanded\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
-\unexpanded\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
-\unexpanded\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
-\unexpanded\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
-\unexpanded\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}
+\permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
+\permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
+\permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
+\permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
+\permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
+\permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}
%D Safeguard against redefinitions:
\appendtoks
- \let\_\normalunderscore % is textunderscore or fakeunderscore
+ \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore
\to \everymathematics
%D Because we may overload \type {\text} in other (structuring) macros, we say:
-\appendtoks \let\text\mathtext \to \everymathematics
+\appendtoks
+ \enforced\let\text\mathtext
+\to \everymathematics
%D The next code is derived from plain \TEX. The names will change!
@@ -2537,7 +2535,7 @@
% this can become an option:
-\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop
+\protected\def\math_display_align_hack % I don't like the global, maybe we should push and pop
{\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip
\math_openup\displayopenupvalue % was \math_openup\jot
\everycr{\noalign{\math_display_align_hack_indeed}}}
@@ -2557,7 +2555,7 @@
%D Text in math:
-\unexpanded\def\mathortext
+\permanent\protected\def\mathortext
{\ifmmode
\expandafter\firstoftwoarguments
\else
@@ -2570,9 +2568,9 @@
\ifdefined\text\else \let\text\hbox \fi
-% \unexpanded\def\mathoptext#1{\mathop{\text{#1}}}
+% \protected\def\mathoptext#1{\mathop{\text{#1}}}
-\unexpanded\def\mathoptext
+\permanent\protected\def\mathoptext
{\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
%\showmathstyle
\dowithnextbox
@@ -2597,15 +2595,15 @@
% new:
-\unexpanded\def\smallmathsymbol#1%
+\permanent\protected\def\smallmathsymbol#1%
{\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath
\triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1%
\normalstopimath}}}}}
% this should be a primitive:
-\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax}
-\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax}
+\permanent\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax}
+\permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax}
% experimental:
@@ -2662,18 +2660,18 @@
{\let\math_inline_openup_start_yes\math_inline_openup_traced_start}
{\let\math_inline_openup_start_yes\math_inline_openup_normal_start}
-\unexpanded\def\math_inline_openup_normal_start
+\protected\def\math_inline_openup_normal_start
{\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax
\scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax
\vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
\begingroup
\let\math_inline_openup_stop\math_inline_openup_normal_stop}
-\unexpanded\def\math_inline_openup_normal_stop
+\protected\def\math_inline_openup_normal_stop
{\endgroup
\vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}
-\unexpanded\def\math_inline_openup_traced_start
+\protected\def\math_inline_openup_traced_start
{\scratchtopoffset \ht\scratchbox
\scratchbottomoffset\dp\scratchbox
\scratchheight \dimexpr\scratchtopoffset +\m_math_inline_openup_ht\relax
@@ -2687,7 +2685,7 @@
\begingroup
\let\math_inline_openup_stop\math_inline_openup_traced_stop}
-\unexpanded\def\math_inline_openup_traced_stop
+\protected\def\math_inline_openup_traced_stop
{\endgroup
\kern-\emwidth
\begingroup
@@ -2702,7 +2700,7 @@
\def\math_inline_openup_start_nop
{\let\math_inline_openup_stop\relax}
-\unexpanded\def\openedupimath
+\permanent\protected\def\openedupimath
{\dontleavehmode
\begingroup
\ifmmode
@@ -2711,7 +2709,7 @@
\expandafter\openedupimath_text
\fi}
-\unexpanded\def\openedupimath_math#1%
+\protected\def\openedupimath_math#1%
{\setbox\scratchbox\mathstylehbox{#1}%
\ifdim\ht\scratchbox>\strutht
\math_inline_openup_start_yes
@@ -2724,7 +2722,7 @@
\math_inline_openup_stop
\endgroup}
-\unexpanded\def\openedupimath_text#1%
+\protected\def\openedupimath_text#1%
{\setbox\scratchbox\hbox{\startimath#1\stopimath}%
\ifdim\ht\scratchbox>\strutht
\math_inline_openup_start_yes
@@ -2743,14 +2741,14 @@
%
% 0x002B=plus 0x2212=minus 0x2013=endash
-\unexpanded\def\mathplus {+}
-\unexpanded\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi}
-\unexpanded\def\mathplusminus{±}
+\permanent\protected\def\mathplus {+}
+\permanent\protected\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi}
+\permanent\protected\def\mathplusminus{±}
%D The \type {\displaywidth} is only known inside a display formula, so we need to catch
%D it when still zero.
-\def\checkeddisplaywidth % hsize if zero
+\permanent\def\checkeddisplaywidth % hsize if zero
{\dimexpr
\ifzeropt\displaywidth
\hsize
@@ -2759,7 +2757,7 @@
\fi
\relax}
-\def\maximizeddisplaywidth % larger than zero but within hsize
+\permanent\def\maximizeddisplaywidth % larger than zero but within hsize
{\dimexpr
\ifzeropt\displaywidth
\hsize
@@ -2801,7 +2799,7 @@
\installcorenamespace{mathrules}
-\unexpanded\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone}
+\permanent\protected\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone}
\appendtoks
\mathrulesmode\ifcsname\??mathrules\fontclass\endcsname
@@ -2824,10 +2822,10 @@
% \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR
% \stoptabulate
-% \unexpanded\def\negenspace{\kern-.5\emwidth}
-% \unexpanded\def\negemspace{\kern- \emwidth}
+% \protected\def\negenspace{\kern-.5\emwidth}
+% \protected\def\negemspace{\kern- \emwidth}
%
-% \unexpanded\def\math_f#1%
+% \protected\def\math_f#1%
% {\ifcase#1\or
% \hairspace
% \or
@@ -2842,7 +2840,7 @@
% \emspace
% \fi}
%
-% \unexpanded\def\math_b#1%
+% \protected\def\math_b#1%
% {\ifcase#1\or
% \neghairspace
% \or
@@ -2864,16 +2862,16 @@
%D Experiment
-\unexpanded\def\math_scripts_stack
+\permanent\protected\def\math_scripts_stack
{\c_attr_mathunstack\attributeunsetvalue}
-\unexpanded\def\math_scripts_unstack
+\permanent\protected\def\math_scripts_unstack
{\clf_enablescriptunstacking
\c_attr_mathunstack\plusone}
\appendtoks
- \let\stackscripts \math_scripts_stack
- \let\unstackscripts\math_scripts_unstack
+ \enforced\let\stackscripts \math_scripts_stack
+ \enforced\let\unstackscripts\math_scripts_unstack
\to \everymathematics
%D Expensive (tracing and inject) but a primitive (using factors) is tricky as we
@@ -2916,7 +2914,7 @@
%D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$
%D \stoptyping
-\unexpanded\def\mathopenupparameter#1#2%
+\permanent\protected\def\mathopenupparameter#1#2%
{\ifmathparameter#1\displaystyle \or\frozen#1\displaystyle #2#1\displaystyle \fi
\ifmathparameter#1\crampeddisplaystyle \or\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi
\ifmathparameter#1\textstyle \or\frozen#1\textstyle #2#1\textstyle \fi
@@ -2942,13 +2940,13 @@
%D \getbuffer
%D \stoplines
-\unexpanded\def\tomathord {\Umathclass\zerocount}
-\unexpanded\def\tomathop {\Umathclass\plusone } % \mathinfix
-\unexpanded\def\tomathbin {\Umathclass\plustwo }
-\unexpanded\def\tomathrel {\Umathclass\plusthree}
-\unexpanded\def\tomathopen {\Umathclass\plusfour } % \mathprefix
-\unexpanded\def\tomathclose{\Umathclass\plusfive } % \mathsuffix
-\unexpanded\def\tomathpunct{\Umathclass\plussix }
+\permanent\protected\def\tomathord {\Umathclass\zerocount}
+\permanent\protected\def\tomathop {\Umathclass\plusone } % \mathinfix
+\permanent\protected\def\tomathbin {\Umathclass\plustwo }
+\permanent\protected\def\tomathrel {\Umathclass\plusthree}
+\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix
+\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix
+\permanent\protected\def\tomathpunct{\Umathclass\plussix }
%D Prescripts. These work in \CONTEXT\ because we have the super- and subscript
%D triggers enabled as active characters but when we would have
@@ -2991,14 +2989,14 @@
% \newtoks \everystartimath
% \newtoks \everystopimath
%
-% \unexpanded\def\startimath{\Ustartmath\the\everystartimath}
-% \unexpanded\def\stopimath {\the\everystopimath\Ustopmath}
+% \protected\def\startimath{\Ustartmath\the\everystartimath}
+% \protected\def\stopimath {\the\everystopimath\Ustopmath}
%
-% \unexpanded\def\m%
+% \protected\def\m%
% {\relax
% \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi}
%
-% \unexpanded\def\math_m_math#1%
+% \protected\def\math_m_math#1%
% {\startimath#1\stopimath}
%
% \let\math_m_stay\firstofoneargument
diff --git a/tex/context/base/mkiv/math-noa.lmt b/tex/context/base/mkiv/math-noa.lmt
new file mode 100644
index 000000000..25e1823e2
--- /dev/null
+++ b/tex/context/base/mkiv/math-noa.lmt
@@ -0,0 +1,2399 @@
+if not modules then modules = { } end modules ['math-noa'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware: this is experimental code and there will be a more generic (attribute value
+-- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will
+-- start cleaning up as by then the bigger picture is clear and code has been used for
+-- years; the main handlers will get some extensions)
+--
+-- we will also make dedicated processors (faster)
+--
+-- beware: names will change as we wil make noads.xxx.handler i.e. xxx
+-- subnamespaces
+
+-- 20D6 -> 2190
+-- 20D7 -> 2192
+
+-- todo: most is mathchar_code so we can have simple dedicated loops
+
+-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types)
+
+local next, tonumber = next, tonumber
+local utfchar, utfbyte = utf.char, utf.byte
+local formatters, gmatch = string.formatters, string.gmatch
+local sortedhash = table.sortedhash
+local insert, remove = table.insert, table.remove
+local div, round = math.div, math.round
+local bor, band = bit32.bor, bit32.band
+
+local fonts = fonts
+local nodes = nodes
+local node = node
+local mathematics = mathematics
+local context = context
+
+local otf = fonts.handlers.otf
+local otffeatures = fonts.constructors.features.otf
+local registerotffeature = otffeatures.register
+
+local privateattribute = attributes.private
+local registertracker = trackers.register
+local registerdirective = directives.register
+local logreporter = logs.reporter
+local setmetatableindex = table.setmetatableindex
+
+local colortracers = nodes.tracers.colors
+
+local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end)
+local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end)
+local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end)
+local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end)
+local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end)
+local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end)
+local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end)
+local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end)
+local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
+local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end)
+local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end)
+local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end)
+local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end)
+local trace_families = false registertracker("math.families", function(v) trace_families = v end)
+local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end)
+local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end)
+
+local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
+
+local report_processing = logreporter("mathematics","processing")
+local report_remapping = logreporter("mathematics","remapping")
+local report_normalizing = logreporter("mathematics","normalizing")
+local report_collapsing = logreporter("mathematics","collapsing")
+local report_fixing = logreporter("mathematics","fixing")
+local report_patching = logreporter("mathematics","patching")
+local report_goodies = logreporter("mathematics","goodies")
+local report_variants = logreporter("mathematics","variants")
+local report_alternates = logreporter("mathematics","alternates")
+local report_italics = logreporter("mathematics","italics")
+local report_kernpairs = logreporter("mathematics","kernpairs")
+local report_domains = logreporter("mathematics","domains")
+local report_families = logreporter("mathematics","families")
+local report_fences = logreporter("mathematics","fences")
+local report_unstacking = logreporter("mathematics","unstack")
+
+local a_mathrendering = privateattribute("mathrendering")
+local a_exportstatus = privateattribute("exportstatus")
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+local tonut = nuts.tonut
+local nutstring = nuts.tostring
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setchar = nuts.setchar
+local setfam = nuts.setfam
+local setsubtype = nuts.setsubtype
+local setattr = nuts.setattr
+local setattrlist = nuts.setattrlist
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getfam = nuts.getfam
+local getattr = nuts.getattr
+local getattrs = nuts.getattrs
+local getlist = nuts.getlist
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+
+local getnucleus = nuts.getnucleus
+local getsub = nuts.getsub
+local getsup = nuts.getsup
+local getsubpre = nuts.getsubpre
+local getsuppre = nuts.getsuppre
+
+local setnucleus = nuts.setnucleus
+local setsub = nuts.setsub
+local setsup = nuts.setsup
+local setsubpre = nuts.setsubpre
+local setsuppre = nuts.setsuppre
+
+local flush_node = nuts.flush
+local copy_node = nuts.copy
+local slide_nodes = nuts.slide
+local set_visual = nuts.setvisual
+
+local mlist_to_hlist = nuts.mlist_to_hlist
+
+local new_kern = nodepool.kern
+local new_submlist = nodepool.submlist
+local new_noad = nodepool.noad
+local new_delimiter = nodepool.delimiter
+local new_fence = nodepool.fence
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+local fontitalics = fonthashes.italics
+
+local variables = interfaces.variables
+local texsetattribute = tex.setattribute
+local texgetattribute = tex.getattribute
+local getfontoffamily = tex.getfontoffamily
+local unsetvalue = attributes.unsetvalue
+local implement = interfaces.implement
+
+local v_reset = variables.reset
+
+local chardata = characters.data
+
+noads = noads or { } -- todo: only here
+local noads = noads
+
+noads.processors = noads.processors or { }
+local processors = noads.processors
+
+noads.handlers = noads.handlers or { }
+local handlers = noads.handlers
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local setaction = tasks.setaction
+
+local nodecodes = nodes.nodecodes
+local noadcodes = nodes.noadcodes
+local fencecodes = nodes.fencecodes
+
+local ordnoad_code = noadcodes.ord
+local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits
+local oplimitsnoad_code = noadcodes.oplimits
+local opnolimitsnoad_code = noadcodes.opnolimits
+local binnoad_code = noadcodes.bin
+local relnode_code = noadcodes.rel
+local opennoad_code = noadcodes.open
+local closenoad_code = noadcodes.close
+local punctnoad_code = noadcodes.punct
+local innernoad_code = noadcodes.inner
+local undernoad_code = noadcodes.under
+local overnoad_code = noadcodes.over
+local vcenternoad_code = noadcodes.vcenter
+local ordlimitsnoad_code = noadcodes.ordlimits or oplimitsnoad_code
+
+local noad_code = nodecodes.noad -- attr nucleus sub sup
+local accent_code = nodecodes.accent -- attr nucleus sub sup accent
+local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
+local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
+local subbox_code = nodecodes.subbox -- attr list
+local submlist_code = nodecodes.submlist -- attr list
+local mathchar_code = nodecodes.mathchar -- attr fam char
+local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
+local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
+----- style_code = nodecodes.style -- attr style
+----- parameter_code = nodecodes.parameter -- attr style
+local math_choice = nodecodes.choice -- attr display text script scriptscript
+local fence_code = nodecodes.fence -- attr subtype
+
+local leftfence_code = fencecodes.left
+local middlefence_code = fencecodes.middle
+local rightfence_code = fencecodes.right
+
+-- local mathclasses = mathematics.classes
+-- local fenceclasses = {
+-- [leftfence_code] = mathclasses.open,
+-- [middlefence_code] = mathclasses.middle,
+-- [rightfence_code] = mathclasses.close,
+-- }
+
+-- this initial stuff is tricky as we can have removed and new nodes with the same address
+-- the only way out is a free-per-page list of nodes (not bad anyway)
+
+-- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt
+-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st
+
+local function process(start,what,n,parent)
+
+ if n then
+ n = n + 1
+ else
+ n = 0
+ end
+ --
+ local initial = start
+ --
+ slide_nodes(start) -- we still miss a prev in noads -- fences test code
+ --
+ while start do
+ local id = getid(start)
+ if trace_processing then
+ if id == noad_code then
+ report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)])
+ elseif id == mathchar_code then
+ local char = getchar(start)
+ local font = getfont(start)
+ local fam = getfam(start)
+ report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char)
+ else
+ report_processing("%w%S",n*2,nutstring(start))
+ end
+ end
+ local proc = what[id]
+ if proc then
+ -- report_processing("start processing")
+ local done, newstart, newinitial = proc(start,what,n,parent) -- prev is bugged: or getprev(start)
+ if newinitial then
+ initial = newinitial -- temp hack .. we will make all return head
+ if newstart then
+ start = newstart
+ -- report_processing("stop processing (new start)")
+ else
+ -- report_processing("quit processing (done)")
+ break
+ end
+ else
+ if newstart then
+ start = newstart
+ -- report_processing("stop processing (new start)")
+ else
+ -- report_processing("stop processing")
+ end
+ end
+ elseif id == noad_code then
+ -- single characters are like this
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
+ if getsubpre then
+ noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list
+ end
+ elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then
+ break
+ elseif id == subbox_code or id == submlist_code then
+ local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !)
+ elseif id == fraction_code then
+ local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
+ noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter
+ elseif id == math_choice then
+ local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list
+ elseif id == fence_code then
+ local noad = getfield(start,"delimiter") if noad then process(noad,what,n,start) end -- delimiter
+ elseif id == radical_code then
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
+ if getsubpre then
+ noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list
+ end
+ noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
+ noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list
+ elseif id == accent_code then
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
+ if getsubpre then
+ noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list
+ end
+ noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list
+ noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list
+ -- elseif id == style_code then
+ -- -- has a next
+ -- elseif id == parameter_code then
+ -- -- has a next
+ -- else
+ -- -- glue, penalty, etc
+ end
+ start = getnext(start)
+ end
+ if not parent then
+ return initial -- only first level -- for now
+ end
+end
+
+local function processnested(current,what,n)
+ local noad = nil
+ local id = getid(current)
+ if id == noad_code then
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list
+ end
+ elseif id == subbox_code or id == submlist_code then
+ noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !)
+ elseif id == fraction_code then
+ noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
+ noad = getfield(current,"right") if noad then process(noad,what,n,current) end -- delimiter
+ elseif id == math_choice then
+ noad = getfield(current,"display") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list
+ elseif id == fence_code then
+ noad = getfield(current,"delimiter") if noad then process(noad,what,n,current) end -- delimiter
+ elseif id == radical_code then
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list
+ end
+ noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
+ noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list
+ elseif id == accent_code then
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list
+ end
+ noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list
+ noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list
+ end
+end
+
+local function processstep(current,process,n,id)
+ local noad = nil
+ local id = id or getid(current)
+ if id == noad_code then
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,n,current) end -- list
+ end
+ elseif id == subbox_code or id == submlist_code then
+ noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !)
+ elseif id == fraction_code then
+ noad = getfield(current,"num") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
+ noad = getfield(current,"right") if noad then process(noad,n,current) end -- delimiter
+ elseif id == math_choice then
+ noad = getfield(current,"display") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"text") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"script") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list
+ elseif id == fence_code then
+ noad = getfield(current,"delimiter") if noad then process(noad,n,current) end -- delimiter
+ elseif id == radical_code then
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,n,current) end -- list
+ end
+ noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
+ noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list
+ elseif id == accent_code then
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
+ if getsubpre then
+ noad = getsuppre (current) if noad then process(noad,n,current) end -- list
+ noad = getsubpre (current) if noad then process(noad,n,current) end -- list
+ end
+ noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list
+ noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list
+ end
+end
+
+local function processnoads(head,actions,banner)
+ if trace_processing then
+ report_processing("start %a",banner)
+ head = process(head,actions)
+ report_processing("stop %a",banner)
+ else
+ head = process(head,actions)
+ end
+ return head
+end
+
+noads.process = processnoads
+noads.processnested = processnested
+noads.processouter = process
+
+-- experiment (when not present fall back to fam 0) -- needs documentation
+
+local unknowns = { }
+local checked = { } -- simple case
+local tracked = false trackers.register("fonts.missing", function(v) tracked = v end)
+local cached = setmetatableindex("table") -- complex case
+
+local function errorchar(font,char)
+ local done = unknowns[char]
+ if done then
+ unknowns[char] = done + 1
+ else
+ unknowns[char] = 1
+ end
+ if tracked then
+ -- slower as we check each font too and we always replace as math has
+ -- more demands than text
+ local fake = cached[font][char]
+ if fake then
+ return fake
+ else
+ local kind, fake = fonts.checkers.placeholder(font,char)
+ if not fake or kind ~= "char" then
+ fake = 0x3F
+ end
+ cached[font][char] = fake
+ return fake
+ end
+ else
+ -- only simple checking, report at the end so one should take
+ -- action anyway ... we can miss a few checks but that is ok
+ -- as there is at least one reported
+ if not checked[char] then
+ if trace_normalizing then
+ report_normalizing("character %C is not available",char)
+ end
+ checked[char] = true
+ end
+ return 0x3F
+ end
+end
+
+-- 0-2 regular
+-- 3-5 bold
+-- 6-8 pseudobold
+
+-- this could best be integrated in the remapper, and if we run into problems, we
+-- might as well do this
+
+do
+
+ local families = { }
+ local a_mathfamily = privateattribute("mathfamily")
+ local boldmap = mathematics.boldmap
+
+ local familymap = { [0] =
+ "regular",
+ "regular",
+ "regular",
+ "bold",
+ "bold",
+ "bold",
+ "pseudobold",
+ "pseudobold",
+ "pseudobold",
+ }
+
+ families[fraction_code] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
+ families[noad_code] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
+ families[mathchar_code] = function(pointer)
+ if getfam(pointer) == 0 then
+ local a = getattr(pointer,a_mathfamily)
+ if a and a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ local char = getchar(pointer)
+ local bold = boldmap[char]
+ local newa = a - 3
+ if not bold then
+ if trace_families then
+ report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
+ end
+ setfam(pointer,newa)
+ elseif not fontcharacters[getfontoffamily(newa)][bold] then
+ if trace_families then
+ report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
+ end
+ if newa > 3 then
+ setfam(pointer,newa-3)
+ end
+ else
+ setattr(pointer,a_exportstatus,char)
+ setchar(pointer,bold)
+ if trace_families then
+ report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa])
+ end
+ setfam(pointer,newa)
+ end
+ else
+ local char = getchar(pointer)
+ if not fontcharacters[getfontoffamily(a)][char] then
+ if trace_families then
+ report_families("no bold replacement for %C",char)
+ end
+ else
+ if trace_families then
+ report_families("family of %C becomes %s with remap %s",char,a,familymap[a])
+ end
+ setfam(pointer,a)
+ end
+ end
+ end
+ end
+ end
+ families[delimiter_code] = function(pointer)
+ if getfield(pointer,"small_fam") == 0 then
+ local a = getattr(pointer,a_mathfamily)
+ if a and a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ -- no bold delimiters in unicode
+ a = a - 3
+ end
+ local char = getfield(pointer,"small_char")
+ local okay = fontcharacters[getfontoffamily(a)][char]
+ if okay then
+ setfield(pointer,"small_fam",a)
+ elseif a > 2 then
+ setfield(pointer,"small_fam",a-3)
+ end
+ local char = getfield(pointer,"large_char")
+ local okay = fontcharacters[getfontoffamily(a)][char]
+ if okay then
+ setfield(pointer,"large_fam",a)
+ elseif a > 2 then
+ setfield(pointer,"large_fam",a-3)
+ end
+ else
+ setfield(pointer,"small_fam",0)
+ setfield(pointer,"large_fam",0)
+ end
+ end
+ end
+
+ -- will become:
+
+ -- families[delimiter_code] = function(pointer)
+ -- if getfam(pointer) == 0 then
+ -- local a = getattr(pointer,a_mathfamily)
+ -- if a and a > 0 then
+ -- setattr(pointer,a_mathfamily,0)
+ -- if a > 5 then
+ -- -- no bold delimiters in unicode
+ -- a = a - 3
+ -- end
+ -- local char = getchar(pointer)
+ -- local okay = fontcharacters[getfontoffamily(a)][char]
+ -- if okay then
+ -- setfam(pointer,a)
+ -- elseif a > 2 then
+ -- setfam(pointer,a-3)
+ -- end
+ -- else
+ -- setfam(pointer,0)
+ -- end
+ -- end
+ -- end
+
+ families[mathtextchar_code] = families[mathchar_code]
+
+ function handlers.families(head,style,penalties)
+ processnoads(head,families,"families")
+ return true -- not needed
+ end
+
+end
+
+-- character remapping
+
+do
+
+ local a_mathalphabet = privateattribute("mathalphabet")
+ local a_mathgreek = privateattribute("mathgreek")
+
+ local relocate = { }
+
+ local remapalphabets = mathematics.remapalphabets
+ local fallbackstyleattr = mathematics.fallbackstyleattr
+ local setnodecolor = colortracers.set
+
+ local function report_remap(tag,id,old,new,extra)
+ report_remapping("remapping %s in font (%s,%s) from %C to %C%s",
+ tag,id,fontdata[id].properties.fontname or "",old,new,extra)
+ end
+
+ local function checked(pointer)
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local data = fontcharacters[font]
+ if not data[char] then
+ local specials = characters.data[char].specials
+ if specials and (specials[1] == "char" or specials[1] == "font") then
+ local newchar = specials[#specials]
+ if trace_remapping then
+ report_remap("fallback",font,char,newchar)
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setattr(pointer,a_exportstatus,char) -- testcase: exponentiale
+ setchar(pointer,newchar)
+ return true
+ end
+ end
+ end
+
+ -- We can optimize this if we really think that math is a bottleneck which it never
+ -- really is.
+
+ relocate[mathchar_code] = function(pointer)
+ local g = getattr(pointer,a_mathgreek) or 0
+ local a = getattr(pointer,a_mathalphabet) or 0
+ -- local g, a = getattrs(pointer,a_mathgreek,a_mathalphabet)
+ -- if not a then a = 0 end
+ -- if not g then g = 0 end
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local characters = fontcharacters[font]
+ if a > 0 or g > 0 then
+ if a > 0 then
+ -- not really critital but we could use properties
+ setattr(pointer,a_mathgreek,0)
+ end
+ if g > 0 then
+ -- not really critital but we could use properties
+ setattr(pointer,a_mathalphabet,0)
+ end
+ local newchar = remapalphabets(char,a,g)
+ if newchar then
+ local newchardata = characters[newchar]
+ if newchardata then
+ if trace_remapping then
+ report_remap("char",font,char,newchar,newchardata.commands and " (virtual)" or "")
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setchar(pointer,newchar)
+ return true
+ else
+ local fallback = fallbackstyleattr(a)
+ if fallback then
+ local newchar = remapalphabets(char,fallback,g)
+ if newchar then
+ if characters[newchar] then
+ if trace_remapping then
+ report_remap("char",font,char,newchar," (fallback remapping used)")
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ setchar(pointer,newchar)
+ return true
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback character)")
+ end
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback remap character)")
+ end
+ elseif trace_remapping then
+ report_remap("char",font,char,newchar," fails (no fallback style)")
+ end
+ end
+ elseif trace_remapping then
+ local chardata = characters[char]
+ if chardata and chardata.commands then
+ report_remap("char",font,char,char," (virtual)")
+ end
+ end
+ end
+ if not characters[char] then
+ setchar(pointer,errorchar(font,char))
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:medi")
+ end
+ if check_coverage then
+ return checked(pointer)
+ end
+ end
+
+ relocate[mathtextchar_code] = function(pointer)
+ if trace_analyzing then
+ setnodecolor(pointer,"font:init")
+ end
+ end
+
+ relocate[delimiter_code] = function(pointer)
+ if trace_analyzing then
+ setnodecolor(pointer,"font:fina")
+ end
+ end
+
+ function handlers.relocate(head,style,penalties)
+ processnoads(head,relocate,"relocate")
+ return true -- not needed
+ end
+
+end
+
+-- rendering (beware, not exported)
+
+do
+
+ local render = { }
+
+ local rendersets = mathematics.renderings.numbers or { } -- store
+
+ render[mathchar_code] = function(pointer)
+ local attr = getattr(pointer,a_mathrendering)
+ if attr and attr > 0 then
+ local char = getchar(pointer)
+ local renderset = rendersets[attr]
+ if renderset then
+ local newchar = renderset[char]
+ if newchar then
+ local font = getfont(pointer)
+ local characters = fontcharacters[font]
+ if characters and characters[newchar] then
+ setchar(pointer,newchar)
+ setattr(pointer,a_exportstatus,char)
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.render(head,style,penalties)
+ processnoads(head,render,"render")
+ return true -- not needed
+ end
+
+end
+
+-- some resize options (this works ok because the content is
+-- empty and no larger next will be forced)
+--
+-- beware: we don't use \delcode but \Udelcode and as such have
+-- no large_fam; also, we need to check for subtype and/or
+-- small_fam not being 0 because \. sits in 0,0 by default
+--
+-- todo: just replace the character by an ord noad
+-- and remove the right delimiter as well
+
+do
+
+ local a_mathsize = privateattribute("mathsize") -- this might move into other fence code
+ local resize = { }
+
+ resize[fence_code] = function(pointer)
+ local subtype = getsubtype(pointer)
+ if subtype == leftfence_code or subtype == rightfence_code then
+ local a = getattr(pointer,a_mathsize)
+ if a and a > 0 then
+ local method = div(a,100)
+ local size = a % 100
+ setattr(pointer,a_mathsize,0)
+ local delimiter = getfield(pointer,"delimiter")
+ local chr = getchar(delimiter)
+ if chr > 0 then
+ local fam = getfam(delimiter)
+ local id = getfontoffamily(fam)
+ if id > 0 then
+ local data = fontdata[id]
+ local char = mathematics.big(data,chr,size,method)
+ local ht = getheight(pointer)
+ local dp = getdepth(pointer)
+ if ht == 1 or dp == 1 then -- 1 scaled point is a signal
+ local chardata = data.characters[char]
+ if ht == 1 then
+ setheight(pointer,chardata.height)
+ end
+ if dp == 1 then
+ setdepth(pointer,chardata.depth)
+ end
+ end
+ if trace_fences then
+ report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size)
+ end
+ setchar(delimiter,char)
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.resize(head,style,penalties)
+ processnoads(head,resize,"resize")
+ return true -- not needed
+ end
+
+end
+
+-- still not perfect:
+
+do
+
+ local a_autofence = privateattribute("mathautofence")
+ local autofences = { }
+ local dummyfencechar = 0x2E
+
+ local function makefence(what,char)
+ local d = new_delimiter() -- todo: attr
+ local f = new_fence() -- todo: attr
+ if char then
+ local sym = getnucleus(char)
+ local chr = getchar(sym)
+ local fam = getfam(sym)
+ if chr == dummyfencechar then
+ chr = 0
+ end
+ setchar(d,chr)
+ setfam(d,fam)
+ flush_node(sym)
+ end
+ setattrlist(d,char)
+ setattrlist(f,char)
+ setsubtype(f,what)
+ setfield(f,"delimiter",d)
+ setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what]
+ return f
+ end
+
+ local function show(where,pointer)
+ print("")
+ local i = 0
+ for n in nuts.traverse(pointer) do
+ i = i + 1
+ print(i,where,nuts.tonode(n))
+ end
+ print("")
+ end
+
+ local function makelist(middle,noad,f_o,o_next,c_prev,f_c)
+-- report_fences(
+-- "middle %s, noad %s, open %s, opennext %s, closeprev %s, close %s",
+-- middle or "?",
+-- noad or "?",
+-- f_o or "?",
+-- o_next or "?",
+-- c_prev or "?",
+-- f_c or "?"
+-- )
+ local list = new_submlist()
+ setsubtype(noad,innernoad_code)
+ setnucleus(noad,list)
+ setlist(list,f_o)
+ setlink(f_o,o_next) -- prev of list is nil
+ setlink(c_prev,f_c) -- next of list is nil
+-- show("list",f_o)
+ if middle and next(middle) then
+ local prev = f_o
+ local current = o_next
+ while current ~= f_c do
+ local midl = middle[current]
+ local next = getnext(current)
+ if midl then
+ local fence = makefence(middlefence_code,current)
+ setnucleus(current)
+ flush_node(current)
+ middle[current] = nil
+ -- replace_node
+ setlink(prev,fence,next)
+ prev = fence
+ else
+ prev = current
+ end
+ current = next
+ end
+ end
+ return noad
+ end
+
+ -- relinking is now somewhat overdone
+
+ local function convert_both(open,close,middle)
+ local o_next = getnext(open)
+ if o_next == close then
+ return close
+ else
+ local c_prev, c_next = getboth(close)
+ local f_o = makefence(leftfence_code,open)
+ local f_c = makefence(rightfence_code,close)
+ makelist(middle,open,f_o,o_next,c_prev,f_c)
+ setnucleus(close)
+ flush_node(close)
+ -- open is now a list
+ setlink(open,c_next)
+ return open
+ end
+ end
+
+ local function convert_open(open,last,middle) -- last is really last (final case)
+ local f_o = makefence(leftfence_code,open)
+ local f_c = makefence(rightfence_code)
+ local o_next = getnext(open)
+ makelist(middle,open,f_o,o_next,last,nil)
+ -- open is now a list
+ setlink(open,l_next)
+ return open
+ end
+
+ local function convert_close(first,close,middle)
+ local f_o = makefence(leftfence_code)
+ local f_c = makefence(rightfence_code,close)
+ local c_prev = getprev(close)
+ local f_next = getnext(first)
+ makelist(middle, close, f_o,f_next,c_prev,f_c)
+ -- close is now a list
+ if c_prev ~= first then
+ setlink(first,close)
+ end
+ return close
+ end
+
+ local stacks = setmetatableindex("table")
+
+ -- 1=open 2=close 3=middle 4=both
+
+ local function processfences(pointer,n,parent)
+ local current = pointer
+ local last = pointer
+ local start = pointer
+ local done = false
+ local initial = pointer
+ local stack = nil
+ local middle = nil -- todo: use properties
+ while current do
+-- show("before",pointer)
+ local id = getid(current)
+ if id == noad_code then
+ local a = getattr(current,a_autofence)
+ if a and a > 0 then
+ local stack = stacks[n]
+ setattr(current,a_autofence,0) -- hm, better use a property
+ local level = #stack
+ if a == 1 then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"open","open")
+ end
+ insert(stack,current)
+ elseif a == 2 then
+ local open = remove(stack)
+ if open then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","both")
+ end
+ current = convert_both(open,current,middle)
+ elseif current == start then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","skip")
+ end
+ else
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","close")
+ end
+ current = convert_close(initial,current,middle)
+ if not parent then
+ initial = current
+ end
+ end
+ elseif a == 3 then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"middle","middle")
+ end
+ if middle then
+ middle[current] = last
+ else
+ middle = { [current] = last }
+ end
+ elseif a == 4 then
+ if not stack or #stack == 0 then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","open")
+ end
+ insert(stack,current)
+ else
+ local open = remove(stack)
+ if open then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","both")
+ end
+ current = convert_both(open,current,middle)
+ elseif current == start then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","skip")
+ end
+ else
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","close")
+ end
+ current = convert_close(initial,current,middle)
+ if not parent then
+ initial = current
+ end
+ end
+ end
+ end
+ done = true
+ else
+ processstep(current,processfences,n+1,id)
+ end
+ else
+ -- next at current level
+ processstep(current,processfences,n,id)
+ end
+-- show("after",pointer)
+ last = current
+ current = getnext(current)
+ end
+ if done then
+ local stack = stacks[n]
+ local s = #stack
+ if s > 0 then
+ for i=1,s do
+ local open = remove(stack)
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,#stack,"flush","open")
+ end
+ last = convert_open(open,last,middle)
+ end
+-- show("done",pointer)
+ end
+ end
+ end
+
+ -- we can have a first changed node .. an option is to have a leading dummy node in math
+ -- lists like the par node as it can save a lot of mess
+
+ local enabled = false
+
+ implement {
+ name = "enableautofences",
+ onlyonce = true,
+ actions = function()
+ enableaction("math","noads.handlers.autofences")
+ enabled = true
+ end
+ }
+
+ function handlers.autofences(head,style,penalties)
+ if enabled then -- tex.modes.c_math_fences_auto
+ -- inspect(nodes.totree(head))
+ processfences(head,1)
+ -- inspect(nodes.totree(head))
+ end
+ end
+
+end
+
+-- normalize scripts
+
+do
+
+ local unscript = { } noads.processors.unscript = unscript
+ local superscripts = characters.superscripts
+ local subscripts = characters.subscripts
+ local fractions = characters.fractions
+ local replaced = { }
+
+ local function replace(pointer,what,n,parent)
+ pointer = parent -- we're following the parent list (chars trigger this)
+ local next = getnext(pointer)
+ local start_super, stop_super, start_sub, stop_sub
+ local mode = "unset"
+ while next and getid(next) == noad_code do
+ local nextnucleus = getnucleus(next)
+ if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then
+ local char = getchar(nextnucleus)
+ local s = superscripts[char]
+ if s then
+ if not start_super then
+ start_super = next
+ mode = "super"
+ elseif mode == "sub" then
+ break
+ end
+ stop_super = next
+ next = getnext(next)
+ setchar(nextnucleus,s)
+ replaced[char] = (replaced[char] or 0) + 1
+ if trace_normalizing then
+ report_normalizing("superscript %C becomes %C",char,s)
+ end
+ else
+ local s = subscripts[char]
+ if s then
+ if not start_sub then
+ start_sub = next
+ mode = "sub"
+ elseif mode == "super" then
+ break
+ end
+ stop_sub = next
+ next = getnext(next)
+ setchar(nextnucleus,s)
+ replaced[char] = (replaced[char] or 0) + 1
+ if trace_normalizing then
+ report_normalizing("subscript %C becomes %C",char,s)
+ end
+ else
+ break
+ end
+ end
+ else
+ break
+ end
+ end
+ if start_super then
+ if start_super == stop_super then
+ setsup(pointer,getnucleus(start_super))
+ else
+ local list = new_submlist() -- todo attr
+ setlist(list,start_super)
+ setsup(pointer,list)
+ end
+ if mode == "super" then
+ setnext(pointer,getnext(stop_super))
+ end
+ setnext(stop_super)
+ end
+ if start_sub then
+
+-- if mode == "sub" then
+-- local sup = getsup(pointer)
+-- if sup and not getsub(pointer) then
+-- local nxt = getnext(pointer)
+-- local new = new_noad(pointer)
+-- setnucleus(new,new_submlist())
+-- setlink(pointer,new,nxt)
+-- pointer = new
+-- end
+-- end
+
+ if start_sub == stop_sub then
+ setsub(pointer,getnucleus(start_sub))
+ else
+ local list = new_submlist() -- todo attr
+ setlist(list,start_sub)
+ setsub(pointer,list)
+ end
+ if mode == "sub" then
+ setnext(pointer,getnext(stop_sub))
+ end
+ setnext(stop_sub)
+ end
+ -- we could return stop
+ end
+
+ unscript[mathchar_code] = replace -- not noads as we need to recurse
+
+ function handlers.unscript(head,style,penalties)
+ processnoads(head,unscript,"unscript")
+ return true -- not needed
+ end
+
+end
+
+do
+
+ local unstack = { } noads.processors.unstack = unstack
+ local enabled = false
+ local a_unstack = privateattribute("mathunstack")
+
+ unstack[noad_code] = function(pointer)
+ if getattr(pointer,a_unstack) then
+ local sup = getsup(pointer)
+ local sub = getsub(pointer)
+ if sup and sub then
+ -- if trace_unstacking then
+ -- report_unstacking() -- todo ... what to show ...
+ -- end
+ local nxt = getnext(pointer)
+ local new = new_noad(pointer)
+ setnucleus(new,new_submlist())
+ setsub(pointer)
+ setsub(new,sub)
+ setlink(pointer,new,nxt)
+ end
+ end
+ end
+
+ function handlers.unstack(head,style,penalties)
+ if enabled then
+ processnoads(head,unstack,"unstack")
+ return true -- not needed
+ end
+ end
+
+ implement {
+ name = "enablescriptunstacking",
+ onlyonce = true,
+ actions = function()
+ enableaction("math","noads.handlers.unstack")
+ enabled = true
+ end
+ }
+
+end
+
+do
+
+ local function collected(list)
+ if list and next(list) then
+ local n, t = 0, { }
+ for k, v in sortedhash(list) do
+ n = n + 1
+ t[n] = formatters["%C"](k)
+ end
+ return formatters["% t (n=%s)"](t,n)
+ end
+ end
+
+ statistics.register("math script replacements", function()
+ return collected(replaced)
+ end)
+
+ statistics.register("unknown math characters", function()
+ return collected(unknowns)
+ end)
+
+end
+
+-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
+-- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$)
+
+-- todo: set alternate for specific symbols
+-- todo: no need to do this when already loaded
+-- todo: use a fonts.hashes.mathalternates
+
+do
+
+ local last = 0
+
+ local known = setmetatableindex(function(t,k)
+ local v = bor(0,2^last)
+ t[k] = v
+ last = last + 1
+ return v
+ end)
+
+ local defaults = {
+ dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
+ -- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet)
+ }
+
+ local function initializemathalternates(tfmdata)
+ local goodies = tfmdata.goodies
+ local autolist = defaults -- table.copy(defaults)
+
+ local function setthem(newalternates)
+ local resources = tfmdata.resources -- was tfmdata.shared
+ local mathalternates = resources.mathalternates
+ local alternates, attributes, registered, presets
+ if mathalternates then
+ alternates = mathalternates.alternates
+ attributes = mathalternates.attributes
+ registered = mathalternates.registered
+ else
+ alternates, attributes, registered = { }, { }, { }
+ mathalternates = {
+ attributes = attributes,
+ alternates = alternates,
+ registered = registered,
+ presets = { },
+ resets = { },
+ hashes = setmetatableindex("table")
+ }
+ resources.mathalternates = mathalternates
+ end
+ --
+ for name, data in sortedhash(newalternates) do
+ if alternates[name] then
+ -- ignore
+ else
+ local attr = known[name]
+ attributes[attr] = data
+ alternates[name] = attr
+ registered[#registered+1] = attr
+ end
+ end
+ end
+
+ if goodies then
+ local done = { }
+ for i=1,#goodies do
+ -- first one counts
+ -- we can consider sharing the attributes ... todo (only once scan)
+ local mathgoodies = goodies[i].mathematics
+ local alternates = mathgoodies and mathgoodies.alternates
+ if alternates then
+ if trace_goodies then
+ report_goodies("loading alternates for font %a",tfmdata.properties.name)
+ end
+ for k, v in next, autolist do
+ if not alternates[k] then
+ alternates[k] = v
+ end
+ end
+ setthem(alternates)
+ return
+ end
+ end
+ end
+
+ if trace_goodies then
+ report_goodies("loading default alternates for font %a",tfmdata.properties.name)
+ end
+ setthem(autolist)
+
+ end
+
+ registerotffeature {
+ name = "mathalternates",
+ description = "additional math alternative shapes",
+ initializers = {
+ base = initializemathalternates,
+ node = initializemathalternates,
+ }
+ }
+
+ -- local getalternate = otf.getalternate (runtime new method so ...)
+
+ -- todo: not shared but copies ... one never knows
+
+ local a_mathalternate = privateattribute("mathalternate")
+ local alternate = { } -- processors.alternate = alternate
+ local fontdata = fonts.hashes.identifiers
+ local fontresources = fonts.hashes.resources
+
+ local function getalternate(fam,tag,current)
+ local resources = fontresources[getfontoffamily(fam)]
+ local attribute = unsetvalue
+ if resources then
+ local mathalternates = resources.mathalternates
+ if mathalternates then
+ local presets = mathalternates.presets
+ if presets then
+ local resets = mathalternates.resets
+ attribute = presets[tag]
+ if not attribute then
+ attribute = 0
+ local alternates = mathalternates.alternates
+ for s in gmatch(tag,"[^, ]+") do
+ if s == v_reset then
+ resets[tag] = true
+ current = unsetvalue
+ else
+ local a = alternates[s] -- or known[s]
+ if a then
+ attribute = bor(attribute,a)
+ end
+ end
+ end
+ if attribute == 0 then
+ attribute = unsetvalue
+ end
+ presets[tag] = attribute
+ elseif resets[tag] then
+ current = unsetvalue
+ end
+ end
+ end
+ end
+ if attribute > 0 and current and current > 0 then
+ return bor(current,attribute)
+ else
+ return attribute
+ end
+ end
+
+ local function presetalternate(fam,tag)
+ texsetattribute(a_mathalternate,getalternate(fam,tag))
+ end
+
+ implement {
+ name = "presetmathalternate",
+ actions = presetalternate,
+ arguments = { "integer", "string" }
+ }
+
+ local function setalternate(fam,tag)
+ local a = texgetattribute(a_mathalternate)
+ local v = getalternate(fam,tag,a)
+ texsetattribute(a_mathalternate,v)
+ end
+
+ implement {
+ name = "setmathalternate",
+ actions = setalternate,
+ arguments = { "integer", "string" }
+ }
+
+ alternate[mathchar_code] = function(pointer) -- slow
+ local a = getattr(pointer,a_mathalternate)
+ if a and a > 0 then
+ setattr(pointer,a_mathalternate,0)
+ local fontid = getfont(pointer)
+ local resources = fontresources[fontid]
+ if resources then
+ local mathalternates = resources.mathalternates
+ if mathalternates then
+ local attributes = mathalternates.attributes
+ local registered = mathalternates.registered
+ local hashes = mathalternates.hashes
+ for i=1,#registered do
+ local r = registered[i]
+ if band(a,r) ~= 0 then
+ local char = getchar(pointer)
+ local alt = hashes[i][char]
+ if alt == nil then
+ local what = attributes[r]
+ alt = otf.getalternate(fontdata[fontid],char,what.feature,what.value) or false
+ if alt == char then
+ alt = false
+ end
+ hashes[i][char] = alt
+ end
+ if alt then
+ if trace_alternates then
+ local what = attributes[r]
+ report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U",
+ tostring(what.feature),tostring(what.value),getchar(pointer),alt)
+ end
+ setchar(pointer,alt)
+ break
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.alternates(head,style,penalties)
+ processnoads(head,alternate,"alternate")
+ return true -- not needed
+ end
+
+end
+
+-- italics: we assume that only characters matter
+--
+-- = we check for correction first because accessing nodes is slower
+-- = the actual glyph is not that important (we can control it with numbers)
+
+-- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on
+-- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all
+-- those heuristics. We want to deal with it ourselves also in the perspective of mixed math
+-- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and
+-- real ones.
+
+-- in opentype the italic correction of a limop is added to the width and luatex does
+-- some juggling that we want to avoid but we need to do something here (in fact, we could
+-- better fix the width of the character)
+
+do
+
+ local a_mathitalics = privateattribute("mathitalics")
+
+ local italics = { }
+ local default_factor = 1/20
+
+ local setcolor = colortracers.set
+ local resetcolor = colortracers.reset
+ local italic_kern = new_kern
+
+ local c_positive_d = "trace:dg"
+ local c_negative_d = "trace:dr"
+
+ local function insert_kern(current,kern)
+ local sub = new_submlist() -- todo: attr
+ local noad = new_noad() -- todo: attr
+ setlist(sub,kern)
+ setnext(kern,noad)
+ setnucleus(noad,current)
+ return sub
+ end
+
+ registertracker("math.italics.visualize", function(v)
+ if v then
+ italic_kern = function(k)
+ local n = new_kern(k) -- todo: attr
+ set_visual(n,"italic")
+ return n
+ end
+ else
+ italic_kern = new_kern
+ end
+ end)
+
+ local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex)
+
+ local visual = chardata[char].visual
+
+ if method == 1 then
+ -- check on state
+ local italics = fontitalics[font]
+ if italics then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ elseif method == 2 then
+ -- no check
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ elseif method == 3 then
+ -- check on visual
+ if visual == "it" or visual == "bi" then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ elseif method == 4 then
+ -- combination of 1 and 3
+ local italics = fontitalics[font]
+ if italics and (visual == "it" or visual == "bi") then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ end
+
+ end
+
+ italics[mathchar_code] = function(pointer,what,n,parent)
+ local method = getattr(pointer,a_mathitalics)
+ if method and method > 0 and method < 100 then
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local correction, visual = getcorrection(method,font,char)
+ if correction and correction ~= 0 then
+ local next_noad = getnext(parent)
+ if not next_noad then
+ if n == 1 then
+ -- only at the outer level .. will become an option (always,endonly,none)
+ if trace_italics then
+ report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char)
+ end
+ if correction > 0 then
+ correction = correction + 100
+ else
+ correction = correction - 100
+ end
+ correction = round(correction)
+ setattr(pointer,a_mathitalics,correction)
+ setattr(parent,a_mathitalics,correction)
+ return -- so no reset later on
+ end
+ end
+ end
+ end
+ setattr(pointer,a_mathitalics,unsetvalue)
+ end
+
+ function handlers.italics(head,style,penalties)
+ processnoads(head,italics,"italics")
+ return true -- not needed
+ end
+
+ local enable = function()
+ enableaction("math", "noads.handlers.italics")
+ if trace_italics then
+ report_italics("enabling math italics")
+ end
+ -- we enable math (unless already enabled elsewhere)
+ typesetters.italics.enablemath()
+ enable = false
+ end
+
+ -- best do this only on math mode (less overhead)
+
+ function mathematics.setitalics(name)
+ if enable then
+ enable()
+ end
+ texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none
+ end
+
+ function mathematics.getitalics(name)
+ if enable then
+ enable()
+ end
+ context(name and name ~= v_reset and tonumber(name) or unsetvalue)
+ end
+
+ function mathematics.resetitalics()
+ texsetattribute(a_mathitalics,unsetvalue)
+ end
+
+ implement {
+ name = "initializemathitalics",
+ actions = enable,
+ onlyonce = true,
+ }
+
+ implement {
+ name = "setmathitalics",
+ actions = mathematics.setitalics,
+ arguments = "string",
+ }
+
+ implement {
+ name = "getmathitalics",
+ actions = mathematics.getitalics,
+ arguments = "string",
+ }
+
+ implement {
+ name = "resetmathitalics",
+ actions = mathematics.resetitalics
+ }
+
+end
+
+do
+
+ -- math kerns (experiment) in goodies:
+ --
+ -- mathematics = {
+ -- kernpairs = {
+ -- [0x1D44E] = {
+ -- [0x1D44F] = 400, -- 𝑎𝑏
+ -- }
+ -- },
+ -- }
+
+ local a_kernpairs = privateattribute("mathkernpairs")
+ local kernpairs = { }
+
+ local function enable()
+ enableaction("math", "noads.handlers.kernpairs")
+ if trace_kernpairs then
+ report_kernpairs("enabling math kern pairs")
+ end
+ enable = false
+ end
+
+ implement {
+ name = "initializemathkernpairs",
+ actions = enable,
+ onlyonce = true,
+ }
+
+ local hash = setmetatableindex(function(t,font)
+ local g = fontdata[font].goodies
+ local m = g and g[1] and g[1].mathematics
+ local k = m and m.kernpairs
+ t[font] = k
+ return k
+ end)
+
+ -- no correction after prime because that moved to a superscript
+
+ kernpairs[mathchar_code] = function(pointer,what,n,parent)
+ if getattr(pointer,a_kernpairs) == 1 then
+ local font = getfont(pointer)
+ local list = hash[font]
+ if list then
+ local first = getchar(pointer)
+ local found = list[first]
+ if found then
+ local next = getnext(parent)
+ if next and getid(next) == noad_code then
+ pointer = getnucleus(next)
+ if pointer then
+ if getfont(pointer) == font then
+ local second = getchar(pointer)
+ local kern = found[second]
+ if kern then
+ kern = kern * fonts.hashes.parameters[font].hfactor
+ if trace_kernpairs then
+ report_kernpairs("adding %p kerning between %C and %C",kern,first,second)
+ end
+ setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.kernpairs(head,style,penalties)
+ processnoads(head,kernpairs,"kernpairs")
+ return true -- not needed
+ end
+
+end
+
+-- primes and such
+
+do
+
+ -- is validpair stil needed?
+
+ local a_mathcollapsing = privateattribute("mathcollapsing")
+ local collapse = { }
+ local mathlists = characters.mathlists
+ local validpair = {
+ [ordnoad_code] = true,
+ [opdisplaylimitsnoad_code] = true,
+ [oplimitsnoad_code] = true,
+ [opnolimitsnoad_code] = true,
+ [binnoad_code] = true, -- new
+ [relnode_code] = true,
+ [opennoad_code] = true, -- new
+ [closenoad_code] = true, -- new
+ [punctnoad_code] = true, -- new
+ [innernoad_code] = false,
+ [undernoad_code] = false,
+ [overnoad_code] = false,
+ [vcenternoad_code] = false,
+ [ordlimitsnoad_code] = true,
+ }
+
+ local reported = setmetatableindex("table")
+
+ collapse[mathchar_code] = function(pointer,what,n,parent)
+
+ if parent and mathlists[getchar(pointer)] then
+ local found, last, lucleus, lsup, lsub, category
+ local tree = mathlists
+ local current = parent
+ while current and validpair[getsubtype(current)] do
+ local nucleus = getnucleus(current) -- == pointer
+ local sub = getsub(current)
+ local sup = getsup(current)
+ local char = getchar(nucleus)
+ if char then
+ local match = tree[char]
+ if match then
+ local method = getattr(current,a_mathcollapsing)
+ if method and method > 0 and method <= 3 then
+ local specials = match.specials
+ local mathlist = match.mathlist
+ local ligature
+ if method == 1 then
+ ligature = specials
+ elseif method == 2 then
+ ligature = specials or mathlist
+ else -- 3
+ ligature = mathlist or specials
+ end
+ if ligature then
+ category = mathlist and "mathlist" or "specials"
+ found = ligature
+ last = current
+ lucleus = nucleus
+ lsup = sup
+ lsub = sub
+ end
+ tree = match
+ if sub or sup then
+ break
+ else
+ current = getnext(current)
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if found and last and lucleus then
+ local id = getfont(lucleus)
+ local characters = fontcharacters[id]
+ local replace = characters and characters[found]
+ if not replace then
+ if not reported[id][found] then
+ reported[id][found] = true
+ report_collapsing("%s ligature %C from %s","ignoring",found,category)
+ end
+ elseif trace_collapsing then
+ report_collapsing("%s ligature %C from %s","creating",found,category)
+ end
+ setchar(pointer,found)
+ local l = getnext(last)
+ local c = getnext(parent)
+ if lsub then
+ setsub(parent,lsub)
+ setsub(last)
+ end
+ if lsup then
+ setsup(parent,lsup)
+ setsup(last)
+ end
+ while c ~= l do
+ local n = getnext(c)
+ flush_node(c)
+ c = n
+ end
+ setlink(parent,l)
+ end
+ end
+ end
+
+ function noads.handlers.collapse(head,style,penalties)
+ processnoads(head,collapse,"collapse")
+ return true -- not needed
+ end
+
+ local enable = function()
+ enableaction("math", "noads.handlers.collapse")
+ if trace_collapsing then
+ report_collapsing("enabling math collapsing")
+ end
+ enable = false
+ end
+
+ implement {
+ name = "initializemathcollapsing",
+ actions = enable,
+ onlyonce = true,
+ }
+
+end
+
+do
+ -- inner under over vcenter
+
+ local fixscripts = { }
+ local movesub = {
+ -- primes
+ [0x2032] = 0xFE932,
+ [0x2033] = 0xFE933,
+ [0x2034] = 0xFE934,
+ [0x2057] = 0xFE957,
+ -- reverse primes
+ [0x2035] = 0xFE935,
+ [0x2036] = 0xFE936,
+ [0x2037] = 0xFE937,
+ }
+
+ mathematics.virtualize(movesub)
+
+ local options_supported = tokens.defined("Unosuperscript")
+
+ local function fixsupscript(parent,current,current_char,new_char)
+ if new_char ~= current_char and new_char ~= true then
+ setchar(current,new_char)
+ if trace_fixing then
+ report_fixing("fixing subscript, replacing superscript %U by %U",current_char,new_char)
+ end
+ else
+ if trace_fixing then
+ report_fixing("fixing subscript, superscript %U",current_char)
+ end
+ end
+ if options_supported then
+ setfield(parent,"options",0x08+0x22)
+ end
+ end
+
+ -- local function movesubscript(parent,current_nucleus,oldchar,newchar)
+ -- local prev = getprev(parent)
+ -- if prev and getid(prev) == noad_code then
+ -- local psup = getsup(prev)
+ -- local psub = getsub(prev)
+ -- if not psup and not psub then
+ -- fixsupscript(prev,current_nucleus,oldchar,newchar)
+ -- local nucleus = getnucleus(parent)
+ -- local sub = getsub(parent)
+ -- setsup(prev,nucleus)
+ -- setsub(prev,sub)
+ -- local dummy = copy_node(nucleus)
+ -- setchar(dummy,0)
+ -- setnucleus(parent,dummy)
+ -- setsub(parent)
+ -- elseif not psup then
+ -- fixsupscript(prev,current_nucleus,oldchar,newchar)
+ -- local nucleus = getnucleus(parent)
+ -- setsup(prev,nucleus)
+ -- local dummy = copy_node(nucleus)
+ -- setchar(dummy,0)
+ -- setnucleus(parent,dummy)
+ -- end
+ -- end
+ -- end
+
+ local function move_none_none(parent,prev,nuc,oldchar,newchar)
+ fixsupscript(prev,nuc,oldchar,newchar)
+ local sub = getsub(parent)
+ setsup(prev,nuc)
+ setsub(prev,sub)
+ local dummy = copy_node(nuc)
+ setchar(dummy,0)
+ setnucleus(parent,dummy)
+ setsub(parent)
+ end
+
+ local function move_none_psub(parent,prev,nuc,oldchar,newchar)
+ fixsupscript(prev,nuc,oldchar,newchar)
+ setsup(prev,nuc)
+ local dummy = copy_node(nuc)
+ setchar(dummy,0)
+ setnucleus(parent,dummy)
+ end
+
+ fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
+ if parent then
+ local oldchar = getchar(pointer)
+ local newchar = movesub[oldchar]
+ if newchar then
+ local nuc = getnucleus(parent)
+ if pointer == nuc then
+ local sub = getsub(pointer)
+ local sup = getsup(pointer)
+ if sub then
+ if sup then
+ -- print("[char] sub sup")
+ else
+ -- print("[char] sub ---")
+ end
+ elseif sup then
+ -- print("[char] --- sup")
+ else
+ local prev = getprev(parent)
+ if prev and getid(prev) == noad_code then
+ local psub = getsub(prev)
+ local psup = getsup(prev)
+ if psub then
+ if psup then
+ -- print("sub sup [char] --- ---")
+ else
+ -- print("sub --- [char] --- ---")
+ move_none_psub(parent,prev,nuc,oldchar,newchar)
+ end
+ elseif psup then
+ -- print("--- sup [char] --- ---")
+ else
+ -- print("[char] --- ---")
+ move_none_none(parent,prev,nuc,oldchar,newchar)
+ end
+ else
+ -- print("no prev [char]")
+ end
+ end
+ else
+ -- print("[char]")
+ end
+ end
+ end
+ end
+
+ function noads.handlers.fixscripts(head,style,penalties)
+ processnoads(head,fixscripts,"fixscripts")
+ return true -- not needed
+ end
+
+end
+
+-- variants
+
+do
+
+ local variants = { }
+ local validvariants = { -- fast check on valid
+ [0x2229] = 0xFE00, [0x222A] = 0xFE00,
+ [0x2268] = 0xFE00, [0x2269] = 0xFE00,
+ [0x2272] = 0xFE00, [0x2273] = 0xFE00,
+ [0x228A] = 0xFE00, [0x228B] = 0xFE00,
+ [0x2293] = 0xFE00, [0x2294] = 0xFE00,
+ [0x2295] = 0xFE00,
+ [0x2297] = 0xFE00,
+ [0x229C] = 0xFE00,
+ [0x22DA] = 0xFE00, [0x22DB] = 0xFE00,
+ [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00,
+ [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00,
+ [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00,
+ [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00,
+ }
+
+ variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value
+ local char = getchar(pointer)
+ local selector = validvariants[char]
+ if selector then
+ local next = getnext(parent)
+ if next and getid(next) == noad_code then
+ local nucleus = getnucleus(next)
+ if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then
+ local variant
+ local tfmdata = fontdata[getfont(pointer)]
+ local mathvariants = tfmdata.resources.variants -- and variantdata
+ if mathvariants then
+ mathvariants = mathvariants[selector]
+ if mathvariants then
+ variant = mathvariants[char]
+ end
+ end
+ if variant then
+ setchar(pointer,variant)
+ setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup
+ if trace_variants then
+ report_variants("variant (%U,%U) replaced by %U",char,selector,variant)
+ end
+ else
+ if trace_variants then
+ report_variants("no variant (%U,%U)",char,selector)
+ end
+ end
+ setprev(next,pointer)
+ setnext(parent,getnext(next))
+ flush_node(next)
+ end
+ end
+ end
+ end
+
+ function handlers.variants(head,style,penalties)
+ processnoads(head,variants,"unicode variant")
+ return true -- not needed
+ end
+
+end
+
+-- for manuals
+
+do
+
+ local classes = { }
+ local colors = {
+ [relnode_code] = "trace:dr",
+ [ordnoad_code] = "trace:db",
+ [binnoad_code] = "trace:dg",
+ [opennoad_code] = "trace:dm",
+ [closenoad_code] = "trace:dm",
+ [punctnoad_code] = "trace:dc",
+ -- [opdisplaylimitsnoad_code] = "",
+ -- [oplimitsnoad_code] = "",
+ -- [opnolimitsnoad_code] = "",
+ -- [ordlimitsnoad_code] = "",
+ -- [innernoad_code = "",
+ -- [undernoad_code] = "",
+ -- [overnoad_code] = "",
+ -- [vcenternoad_code] = "",
+ }
+
+ local setcolor = colortracers.set
+ local resetcolor = colortracers.reset
+
+ classes[mathchar_code] = function(pointer,what,n,parent)
+ local color = colors[getsubtype(parent)]
+ if color then
+ setcolor(pointer,color)
+ else
+ resetcolor(pointer)
+ end
+ end
+
+ function handlers.classes(head,style,penalties)
+ processnoads(head,classes,"classes")
+ return true -- not needed
+ end
+
+ registertracker("math.classes",function(v)
+ setaction("math","noads.handlers.classes",v)
+ end)
+
+end
+
+-- experimental
+
+do
+
+ -- mathematics.registerdomain {
+ -- name = "foo",
+ -- parents = { "bar" },
+ -- characters = {
+ -- [0x123] = { char = 0x234, class = binary },
+ -- },
+ -- }
+
+ local domains = { }
+ local categories = { }
+ local numbers = { }
+ local a_mathdomain = privateattribute("mathdomain")
+ mathematics.domains = categories
+ local permitted = {
+ ordinary = ordnoad_code,
+ binary = binnoad_code,
+ relation = relnode_code,
+ punctuation = punctnoad_code,
+ inner = innernoad_code,
+ }
+
+ function mathematics.registerdomain(data)
+ local name = data.name
+ if not name then
+ return
+ end
+ local attr = #numbers + 1
+ categories[name] = data
+ numbers[attr] = data
+ data.attribute = attr
+ -- we delay hashing
+ return attr
+ end
+
+ local enable
+
+ enable = function()
+ enableaction("math", "noads.handlers.domains")
+ if trace_domains then
+ report_domains("enabling math domains")
+ end
+ enable = false
+ end
+
+ function mathematics.setdomain(name)
+ if enable then
+ enable()
+ end
+ local data = name and name ~= v_reset and categories[name]
+ texsetattribute(a_mathdomain,data and data.attribute or unsetvalue)
+ end
+
+ function mathematics.getdomain(name)
+ if enable then
+ enable()
+ end
+ local data = name and name ~= v_reset and categories[name]
+ context(data and data.attribute or unsetvalue)
+ end
+
+ implement {
+ name = "initializemathdomain",
+ actions = enable,
+ onlyonce = true,
+ }
+
+ implement {
+ name = "setmathdomain",
+ arguments = "string",
+ actions = mathematics.setdomain,
+ }
+
+ implement {
+ name = "getmathdomain",
+ arguments = "string",
+ actions = mathematics.getdomain,
+ }
+
+ local function makehash(data)
+ local hash = { }
+ local parents = data.parents
+ if parents then
+ local function merge(name)
+ if name then
+ local c = categories[name]
+ if c then
+ local hash = c.hash
+ if not hash then
+ hash = makehash(c)
+ end
+ for k, v in next, hash do
+ hash[k] = v
+ end
+ end
+ end
+ end
+ if type(parents) == "string" then
+ merge(parents)
+ elseif type(parents) == "table" then
+ for i=1,#parents do
+ merge(parents[i])
+ end
+ end
+ end
+ local characters = data.characters
+ if characters then
+ for k, v in next, characters do
+ -- local chr = n.char
+ local cls = v.class
+ if cls then
+ v.code = permitted[cls]
+ else
+ -- invalid class
+ end
+ hash[k] = v
+ end
+ end
+ data.hash = hash
+ return hash
+ end
+
+ domains[mathchar_code] = function(pointer,what,n,parent)
+ local attr = getattr(pointer,a_mathdomain)
+ if attr then
+ local domain = numbers[attr]
+ if domain then
+ local hash = domain.hash
+ if not hash then
+ hash = makehash(domain)
+ end
+ local char = getchar(pointer)
+ local okay = hash[char]
+ if okay then
+ local chr = okay.char
+ local cls = okay.code
+ if chr and chr ~= char then
+ setchar(pointer,chr)
+ end
+ if cls and cls ~= getsubtype(parent) then
+ setsubtype(parent,cls)
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.domains(head,style,penalties)
+ processnoads(head,domains,"domains")
+ return true -- not needed
+ end
+
+end
+
+-- just for me
+
+function handlers.showtree(head,style,penalties)
+ inspect(nodes.totree(tonut(head)))
+end
+
+registertracker("math.showtree",function(v)
+ setaction("math","noads.handlers.showtree",v)
+end)
+
+-- also for me
+
+do
+
+ local applyvisuals = nuts.applyvisuals
+ local visual = false
+
+ function handlers.makeup(head)
+ applyvisuals(head,visual)
+ end
+
+ registertracker("math.makeup",function(v)
+ visual = v
+ setaction("math","noads.handlers.makeup",v)
+ end)
+
+end
+
+-- the normal builder
+
+do
+
+ local force_penalties = false
+
+ -- registertracker("math.penalties",function(v)
+ -- force_penalties = v
+ -- end)
+
+ function builders.kernel.mlist_to_hlist(head,style,penalties)
+ return mlist_to_hlist(head,style,force_penalties or penalties)
+ end
+
+ -- function builders.kernel.mlist_to_hlist(head,style,penalties)
+ -- local h = mlist_to_hlist(head,style,force_penalties or penalties)
+ -- inspect(nodes.totree(h,true,true,true))
+ -- return h
+ -- end
+
+ implement {
+ name = "setmathpenalties",
+ arguments = "integer",
+ actions = function(p)
+ force_penalties = p > 0
+ end,
+ }
+
+end
+
+local actions = tasks.actions("math") -- head, style, penalties
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+function processors.mlist_to_hlist(head,style,penalties)
+ starttiming(noads)
+ head = actions(head,style,penalties)
+ stoptiming(noads)
+ return head
+end
+
+callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list")
+
+-- tracing
+
+statistics.register("math processing time", function()
+ return statistics.elapsedseconds(noads)
+end)
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 188363847..1fb763a3b 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -203,7 +203,7 @@ local subbox_code = nodecodes.subbox -- attr list
local submlist_code = nodecodes.submlist -- attr list
local mathchar_code = nodecodes.mathchar -- attr fam char
local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
-local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char
+local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
----- style_code = nodecodes.style -- attr style
----- parameter_code = nodecodes.parameter -- attr style
local math_choice = nodecodes.choice -- attr display text script scriptscript
@@ -282,7 +282,7 @@ local function process(start,what,n,parent)
noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list
noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list
end
- elseif id == mathchar_code or id == mathtextchar_code or id == delim_code then
+ elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then
break
elseif id == subbox_code or id == submlist_code then
local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !)
@@ -583,7 +583,7 @@ do
end
end
end
- families[delim_code] = function(pointer)
+ families[delimiter_code] = function(pointer)
if getfield(pointer,"small_fam") == 0 then
local a = getattr(pointer,a_mathfamily)
if a and a > 0 then
@@ -615,7 +615,7 @@ do
-- will become:
- -- families[delim_code] = function(pointer)
+ -- families[delimiter_code] = function(pointer)
-- if getfam(pointer) == 0 then
-- local a = getattr(pointer,a_mathfamily)
-- if a and a > 0 then
@@ -758,7 +758,7 @@ do
end
end
- relocate[delim_code] = function(pointer)
+ relocate[delimiter_code] = function(pointer)
if trace_analyzing then
setnodecolor(pointer,"font:fina")
end
diff --git a/tex/context/base/mkiv/math-pln.mkxl b/tex/context/base/mkiv/math-pln.mkxl
new file mode 100644
index 000000000..2e090c224
--- /dev/null
+++ b/tex/context/base/mkiv/math-pln.mkxl
@@ -0,0 +1,245 @@
+%D \module
+%D [ file=math-pln,
+%D version=2001.11.16,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Plain Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Here we collect some Plain \TEX\ leftovers.
+
+\writestatus{loading}{ConTeXt Math Macros / Plain Helpers}
+
+\unprotect
+
+% we need proper unicode:
+
+\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to
+
+% might change
+
+\protected\def\hrulefill{\leaders\hrule\hfill}
+\protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill}
+
+% will move
+
+\def\oalign#1%
+ {\leavevmode % plain tex uses this
+ \vtop
+ {\baselineskip\zeroskip
+ \lineskip.25\exheight
+ \ialign{\alignmark\alignmark\crcr#1\crcr}}}
+
+\def\ooalign % chars over each other
+ {\lineskiplimit-\maxdimen
+ \oalign}
+
+% needs checking
+
+\def\choose{\atopwithdelims()}
+\def\brack {\atopwithdelims[]}
+\def\brace {\atopwithdelims\{\}}
+
+% needs checking
+
+\protected\def\buildrel#1\over#2%
+ {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
+
+\protected\def\bmod
+ {\nonscript
+ \mskip-\medmuskip
+ \mkern5mu
+ \mfunction{mod}%
+ \penalty900
+ \mkern5mu
+ \nonscript
+ \mskip-\medmuskip}
+
+\protected\def\pmod#1%
+ {\allowbreak
+ \mkern18mu
+ (\mfunction{mod}\mskip\medmuskip#1)}
+
+\protected\def\cases#1%
+ {\left\{%
+ \mskip\thinmuskip
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{%
+ \normalstartimath\alignmark\alignmark\hfil\normalstopimath
+ \aligntab
+ \quad\alignmark\alignmark\hfil
+ \crcr
+ #1%
+ \crcr}}%
+ \right.}
+
+\protected\def\matrix#1%
+ {\emptyhbox
+ \mskip\thinmuskip
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{%
+ \hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil
+ \aligntab
+ \aligntab
+ \quad\hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil
+ \crcr
+ \mathstrut
+ \crcr
+ \noalign{\kern-\baselineskip}
+ #1\crcr
+ \mathstrut
+ \crcr
+ \noalign{\kern-\baselineskip}}}%
+ \mskip\thinmuskip}
+
+\protected\def\pmatrix#1%
+ {\left(\matrix{#1}\right)}
+
+% \protected\def\openup
+% {\afterassignment\math_openup\scratchdimen=}
+%
+% \def\math_openup
+% {\advance\lineskip \scratchdimen
+% \advance\baselineskip \scratchdimen
+% \advance\lineskiplimit\scratchdimen}
+
+\let\math_closeup\relax
+
+\protected\def\math_openup
+ {\afterassignment\math_openup_indeed\scratchdimen}
+
+\def\math_openup_indeed
+ {\protected\edef\math_closeup
+ {\lineskip \the\lineskip
+ \baselineskip \the\baselineskip
+ \lineskiplimit\the\lineskiplimit
+ \relax}%
+ \advance \lineskip \scratchdimen
+ \advance \baselineskip \scratchdimen
+ \advance \lineskiplimit \scratchdimen}
+
+\let\openup \math_openup
+\def\closeup{\math_closeup} % dynamic
+
+\protected\def\displaylines#1%
+ {\the\mathdisplayaligntweaks
+ \tabskip\zeroskip
+ \halign
+ {\hbox to \displaywidth{%
+ \normalstartimath\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle\alignmark\alignmark\hfil\normalstopimath}\crcr
+ #1\crcr}}
+
+%D This comes from plain but I gave it a \CONTEXT\ touch:
+
+\permanent\def\math_border_NC_indeed
+ {\enforced\global\def\math_border_NC{\aligntab}}
+
+\aliased\let\math_border_NC\math_border_NC_indeed
+
+\permanent\def\math_border_NR
+ {\enforced\global\let\math_border_NC\math_border_NC_indeed
+ \cr}
+
+\protected\def\math_border_matrix#1#2#3% adapted plain
+ {\begingroup
+ %
+ \setbox\scratchbox\hbox\bgroup
+ \mr B%
+ \egroup
+ \scratchdimenone\wd\scratchbox
+ %
+ \scratchdimentwo.2\bodyfontsize
+ %
+ \mathsurround\zeropoint
+ %
+ \enforced\def\NC{\math_border_NC}%
+ \enforced\def\NR{\math_border_NR}%
+ %
+ \gdef\m_math_border_matrix
+ {\kern\scratchdimentwo
+ \glet\m_math_border_matrix\relax}%
+ %
+ \setbox\scratchboxone\vbox\bgroup
+ \everycr{\noalign\bgroup\m_math_border_matrix\egroup}%
+ \tabskip \zeroskip
+ \halign{% \ialign resets everycr
+ \startimath\alignmark\alignmark\stopimath
+ \hfil
+ \kern\dimexpr\scratchdimentwo+\scratchdimenone\relax
+ \aligntab
+ \thinspace
+ \hfil
+ \startimath\alignmark\alignmark\stopimath
+ \hfil
+ \aligntab
+ \aligntab
+ \quad
+ \hfil
+ \startimath\alignmark\alignmark\stopimath
+ \hfil
+ \crcr
+ \omit
+ \strut
+ \hfil
+ \crcr
+ \noalign{\kern-\baselineskip}%
+ #3\crcr
+ \omit
+ \strut
+ \cr}%
+ \egroup
+ \setbox\scratchboxtwo\vbox\bgroup
+ \unvcopy\scratchboxone
+ \global\setbox\globalscratchbox\lastbox
+ \egroup
+ \setbox\scratchboxtwo\hbox\bgroup
+ \unhbox\globalscratchbox
+ \unskip
+ \global\setbox\globalscratchbox\lastbox
+ \egroup
+ \setbox\scratchboxtwo\hbox\bgroup
+ \startimath
+ \kern\dimexpr\wd\globalscratchbox-\scratchdimenone\relax
+ \left#1\relax
+ \kern-\wd\globalscratchbox
+ \global\setbox\globalscratchbox\vbox\bgroup
+ \box\globalscratchbox
+ \kern\scratchdimentwo
+ \egroup
+ \vcenter\bgroup
+ \kern-\ht\globalscratchbox
+ \unvbox\scratchboxone
+ \kern-\baselineskip
+ \egroup
+ \thinspace
+ \right#2\relax
+ \stopimath
+ \egroup
+ \null
+ \thickspace
+ \vbox\bgroup
+ \kern\ht\globalscratchbox
+ \box\scratchboxtwo
+ \egroup
+ %
+ \endgroup}
+
+\permanent\protected\def\bordermatrix {\math_border_matrix()}
+\permanent\protected\def\bbordermatrix{\math_border_matrix[]}
+
+\permanent\protected\def\startbordermatrix #1\stopbordermatrix {\math_border_matrix(){#1}}
+\permanent\protected\def\startbbordermatrix#1\stopbbordermatrix{\math_border_matrix[]{#1}}
+
+\permanent\let\stopbordermatrix \relax
+\permanent\let\stopbbordermatrix\relax
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/math-tag.lmt b/tex/context/base/mkiv/math-tag.lmt
new file mode 100644
index 000000000..eb58b5450
--- /dev/null
+++ b/tex/context/base/mkiv/math-tag.lmt
@@ -0,0 +1,596 @@
+if not modules then modules = { } end modules ['math-tag'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: have a local list with local tags that then get appended
+-- todo: use tex.getmathcodes (no table)
+
+-- use lpeg matchers
+
+local find, match = string.find, string.match
+local insert, remove, concat = table.insert, table.remove, table.concat
+
+local attributes = attributes
+local nodes = nodes
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getlist = nuts.getlist
+local getfield = nuts.getfield
+local getdisc = nuts.getdisc
+local getsubtype = nuts.getsubtype
+local getattr = nuts.getattr
+local getattrlist = nuts.getattrlist
+local setattr = nuts.setattr
+----- getcomponents = nuts.getcomponents -- not really needed
+local getwidth = nuts.getwidth
+
+local getnucleus = nuts.getnucleus
+local getsub = nuts.getsub
+local getsup = nuts.getsup
+
+local set_attributes = nuts.setattributes
+
+local nextnode = nuts.traversers.node
+
+local nodecodes = nodes.nodecodes
+
+local noad_code = nodecodes.noad -- attr nucleus sub sup
+local accent_code = nodecodes.accent -- attr nucleus sub sup accent
+local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
+local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
+local subbox_code = nodecodes.subbox -- attr list
+local submlist_code = nodecodes.submlist -- attr list
+local mathchar_code = nodecodes.mathchar -- attr fam char
+local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
+local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
+local style_code = nodecodes.style -- attr style
+local choice_code = nodecodes.choice -- attr display text script scriptscript
+local fence_code = nodecodes.fence -- attr subtype
+
+local accentcodes = nodes.accentcodes
+local fencecodes = nodes.fencecodes
+
+local fixedtopaccent_code = accentcodes.fixedtop
+local fixedbottomaccent_code = accentcodes.fixedbottom
+local fixedbothaccent_code = accentcodes.fixedboth
+
+local leftfence_code = fencecodes.left
+local middlefence_code = fencecodes.middle
+local rightfence_code = fencecodes.right
+
+local kerncodes = nodes.kerncodes
+
+local fontkern_code = kerncodes.fontkern
+local italickern_code = kerncodes.italickern
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local math_code = nodecodes.math
+
+local processnoads = noads.process
+
+local a_tagged = attributes.private('tagged')
+local a_mathcategory = attributes.private('mathcategory')
+local a_mathmode = attributes.private('mathmode')
+
+local tags = structures.tags
+
+local start_tagged = tags.start
+local restart_tagged = tags.restart
+local stop_tagged = tags.stop
+local taglist = tags.taglist
+
+local chardata = characters.data
+
+local getmathcodes = tex.getmathcodes
+local mathcodes = mathematics.codes
+local ordinary_mathcode = mathcodes.ordinary
+local variable_mathcode = mathcodes.variable
+
+local fromunicode16 = fonts.mappings.fromunicode16
+local fontcharacters = fonts.hashes.characters
+
+local report_tags = logs.reporter("structure","tags")
+
+local process
+
+local function processsubsup(start)
+ -- At some point we might need to add an attribute signaling the
+ -- super- and subscripts because TeX and MathML use a different
+ -- order. The mrows are needed to keep mn's separated.
+ local nucleus = getnucleus(start)
+ local sup = getsup(start)
+ local sub = getsub(start)
+ if sub then
+ if sup then
+ setattr(start,a_tagged,start_tagged("msubsup"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow", { subscript = true })
+ process(sub)
+ stop_tagged()
+ start_tagged("mrow", { superscript = true })
+ process(sup)
+ stop_tagged()
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("msub"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow")
+ process(sub)
+ stop_tagged()
+ stop_tagged()
+ end
+ elseif sup then
+ setattr(start,a_tagged,start_tagged("msup"))
+ -- start_tagged("mrow")
+ process(nucleus)
+ -- stop_tagged()
+ start_tagged("mrow")
+ process(sup)
+ stop_tagged()
+ stop_tagged()
+ else
+ process(nucleus)
+ end
+end
+
+-- todo: check function here and keep attribute the same
+
+-- todo: variants -> original
+
+local actionstack = { }
+local fencesstack = { }
+
+-- glyph nodes and such can happen in under and over stuff
+
+-- local function getunicode(n) -- instead of getchar
+-- local char = getchar(n)
+-- -- local font = getfontoffamily(getfield(n,"fam"))
+-- local font = getfont(n)
+-- local data = fontcharacters[font][char]
+-- return data.unicode or char
+-- end
+
+local function getunicode(n) -- instead of getchar
+ -- local char, font = isglyph(n) -- no, we have a mathchar
+ local char, font = getchar(n), getfont(n)
+ local data = fontcharacters[font][char]
+ return data.unicode or char -- can be a table but unlikely for math characters
+end
+
+-------------------
+
+local content = { }
+local found = false
+
+content[mathchar_code] = function() found = true end
+
+local function hascontent(head)
+ found = false
+ processnoads(head,content,"content")
+ return found
+end
+
+--------------------
+
+-- todo: use properties
+
+-- local function showtag(n,id,old)
+-- local attr = getattr(n,a_tagged)
+-- local curr = tags.current()
+-- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)",
+-- old and "before" or "after ",
+-- nodecodes[id],
+-- getattrlist(n),
+-- attr or "?",attr and taglist[attr].tagname or "?",
+-- curr or "?",curr and taglist[curr].tagname or "?"
+-- )
+-- end
+
+process = function(start) -- we cannot use the processor as we have no finalizers (yet)
+ local mtexttag = nil
+ while start do
+ local id = getid(start)
+-- showtag(start,id,true)
+ if id == glyph_code or id == disc_code then
+ if not mtexttag then
+ mtexttag = start_tagged("mtext")
+ end
+ setattr(start,a_tagged,mtexttag)
+ elseif mtexttag and id == kern_code and (getsubtype(start) == fontkern_code or getsubtype(start) == italickern_code) then -- italickern
+ setattr(start,a_tagged,mtexttag)
+ else
+ if mtexttag then
+ stop_tagged()
+ mtexttag = nil
+ end
+ if id == mathchar_code then
+ local char = getchar(start)
+ local code = getmathcodes(char)
+ local tag
+ if code == ordinary_mathcode or code == variable_mathcode then
+ local ch = chardata[char]
+ local mc = ch and ch.mathclass
+ if mc == "number" then
+ tag = "mn"
+ elseif mc == "variable" or not mc then -- variable is default
+ tag = "mi"
+ else
+ tag = "mo"
+ end
+ else
+ tag = "mo"
+ end
+ local a = getattr(start,a_mathcategory)
+ if a then
+ setattr(start,a_tagged,start_tagged(tag,{ mathcategory = a }))
+ else
+ setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory
+ end
+ stop_tagged()
+ -- showtag(start,id,false)
+ break -- okay?
+ elseif id == mathtextchar_code then -- or id == glyph_code
+ -- check for code
+ local a = getattr(start,a_mathcategory)
+ if a then
+ setattr(start,a_tagged,start_tagged("ms",{ mathcategory = a })) -- mtext
+ else
+ setattr(start,a_tagged,start_tagged("ms")) -- mtext
+ end
+ stop_tagged()
+ -- showtag(start,id,false)
+ break
+ elseif id == delimiter_code then
+ -- check for code
+ setattr(start,a_tagged,start_tagged("mo"))
+ stop_tagged()
+ -- showtag(start,id,false)
+ break
+ elseif id == style_code then
+ -- has a next
+ elseif id == noad_code then
+ -- setattr(start,a_tagged,tags.current())
+ processsubsup(start)
+ elseif id == subbox_code or id == hlist_code or id == vlist_code then
+ -- keep an eye on subbox_code and see what ends up in there
+ local attr = getattr(start,a_tagged)
+ if not attr then
+ -- just skip
+ else
+ local specification = taglist[attr]
+ if specification then
+ local tag = specification.tagname
+ if tag == "formulacaption" then
+ -- skip
+ elseif tag == "mstacker" then
+ local list = getlist(start)
+ if list then
+ process(list)
+ end
+ else
+ if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then
+ tag = "mtext"
+ end
+ local text = start_tagged(tag)
+ setattr(start,a_tagged,text)
+ local list = getlist(start)
+ if not list then
+ -- empty list
+ elseif not attr then
+ -- box comes from strange place
+ set_attributes(list,a_tagged,text) -- only the first node ?
+ else
+ -- Beware, the first node in list is the actual list so we definitely
+ -- need to nest. This approach is a hack, maybe I'll make a proper
+ -- nesting feature to deal with this at another level. Here we just
+ -- fake structure by enforcing the inner one.
+ --
+ -- todo: have a local list with local tags that then get appended
+ --
+ local tagdata = specification.taglist
+ local common = #tagdata + 1
+ local function runner(list,depth) -- quite inefficient
+ local cache = { } -- we can have nested unboxed mess so best local to runner
+ local keep = nil
+ -- local keep = { } -- win case we might need to move keep outside
+ for n, id, subtype in nextnode, list do
+ local mth = id == math_code and subtype
+ if mth == 0 then -- hm left_code
+ -- insert(keep,text)
+ keep = text
+ text = start_tagged("mrow")
+ common = common + 1
+ end
+ local aa = getattr(n,a_tagged)
+ if aa then
+ local ac = cache[aa]
+ if not ac then
+ local tagdata = taglist[aa].taglist
+ local extra = #tagdata
+ if common <= extra then
+ for i=common,extra do
+ ac = restart_tagged(tagdata[i]) -- can be made faster
+ end
+ for i=common,extra do
+ stop_tagged() -- can be made faster
+ end
+ else
+ ac = text
+ end
+ cache[aa] = ac
+ end
+ setattr(n,a_tagged,ac)
+ else
+ setattr(n,a_tagged,text)
+ end
+ if id == hlist_code or id == vlist_code then
+ runner(getlist(n),depth+1)
+ elseif id == glyph_code then
+ -- this should not be needed
+ -- local components = getcomponents(n) -- unlikely set
+ -- if components then
+ -- runner(getcomponent,depth+1)
+ -- end
+ elseif id == disc_code then
+ -- this should not be needed
+ local pre, post, replace = getdisc(n)
+ if pre then
+ runner(pre,depth+1)
+ end
+ if post then
+ runner(post,depth+1)
+ end
+ if replace then
+ runner(replace,depth+1)
+ end
+ end
+ if mth == 1 then
+ stop_tagged()
+ -- text = remove(keep)
+ text = keep
+ common = common - 1
+ end
+ end
+ end
+ runner(list,0)
+ end
+ stop_tagged()
+ end
+ end
+ end
+ elseif id == submlist_code then -- normally a hbox
+ local list = getlist(start)
+ if list then
+ local attr = getattr(start,a_tagged)
+ local last = attr and taglist[attr]
+ if last then
+ local tag = last.tagname
+ local detail = last.detail
+ if tag == "maction" then
+ if detail == "" then
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ elseif actionstack[#actionstack] == action then
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ else
+ insert(actionstack,action)
+ setattr(start,a_tagged,start_tagged("mrow",{ detail = action }))
+ process(list)
+ stop_tagged()
+ remove(actionstack)
+ end
+ elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then
+ -- looks like it gets processed twice
+ -- do we still end up here ?
+ setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute
+ process(list)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ end
+ else -- never happens, we're always document
+ setattr(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ end
+ end
+ elseif id == fraction_code then
+ local num = getfield(start,"num")
+ local denom = getfield(start,"denom")
+ local left = getfield(start,"left")
+ local right = getfield(start,"right")
+ if left then
+ setattr(left,a_tagged,start_tagged("mo"))
+ process(left)
+ stop_tagged()
+ end
+ setattr(start,a_tagged,start_tagged("mfrac"))
+ process(num)
+ process(denom)
+ stop_tagged()
+ if right then
+ setattr(right,a_tagged,start_tagged("mo"))
+ process(right)
+ stop_tagged()
+ end
+ elseif id == choice_code then
+ local display = getfield(start,"display")
+ local text = getfield(start,"text")
+ local script = getfield(start,"script")
+ local scriptscript = getfield(start,"scriptscript")
+ if display then
+ process(display)
+ end
+ if text then
+ process(text)
+ end
+ if script then
+ process(script)
+ end
+ if scriptscript then
+ process(scriptscript)
+ end
+ elseif id == fence_code then
+ local subtype = getsubtype(start)
+ local delim = getfield(start,"delimiter")
+ if subtype == leftfence_code then
+ -- left
+ local properties = { }
+ insert(fencesstack,properties)
+ setattr(start,a_tagged,start_tagged("mfenced",properties)) -- needs checking
+ if delim then
+ start_tagged("ignore")
+ local chr = getchar(delim)
+ if chr ~= 0 then
+ properties.left = chr
+ end
+ process(delim)
+ stop_tagged()
+ end
+ start_tagged("mrow") -- begin of subsequence
+ elseif subtype == middlefence_code then
+ -- middle
+ if delim then
+ start_tagged("ignore")
+ local top = fencesstack[#fencesstack]
+ local chr = getchar(delim)
+ if chr ~= 0 then
+ local mid = top.middle
+ if mid then
+ mid[#mid+1] = chr
+ else
+ top.middle = { chr }
+ end
+ end
+ process(delim)
+ stop_tagged()
+ end
+ stop_tagged() -- end of subsequence
+ start_tagged("mrow") -- begin of subsequence
+ elseif subtype == rightfence_code then
+ local properties = remove(fencesstack)
+ if not properties then
+ report_tags("missing right fence")
+ properties = { }
+ end
+ if delim then
+ start_tagged("ignore")
+ local chr = getchar(delim)
+ if chr ~= 0 then
+ properties.right = chr
+ end
+ process(delim)
+ stop_tagged()
+ end
+ stop_tagged() -- end of subsequence
+ stop_tagged()
+ else
+ -- can't happen
+ end
+ elseif id == radical_code then
+ local left = getfield(start,"left")
+ local degree = getfield(start,"degree")
+ if left then
+ start_tagged("ignore")
+ process(left) -- root symbol, ignored
+ stop_tagged()
+ end
+ if degree and hascontent(degree) then
+ setattr(start,a_tagged,start_tagged("mroot"))
+ processsubsup(start)
+ process(degree)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("msqrt"))
+ processsubsup(start)
+ stop_tagged()
+ end
+ elseif id == accent_code then
+ local subtype = getsubtype(start)
+ local accent = getfield(start,"accent")
+ local bot_accent = getfield(start,"bot_accent")
+ if bot_accent then
+ if accent then
+ setattr(start,a_tagged,start_tagged("munderover", {
+ accent = true,
+ top = getunicode(accent),
+ bottom = getunicode(bot_accent),
+ topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
+ bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
+ }))
+ processsubsup(start)
+ process(bot_accent)
+ process(accent)
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("munder", {
+ accent = true,
+ bottom = getunicode(bot_accent),
+ bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
+ }))
+ processsubsup(start)
+ process(bot_accent)
+ stop_tagged()
+ end
+ elseif accent then
+ setattr(start,a_tagged,start_tagged("mover", {
+ accent = true,
+ top = getunicode(accent),
+ topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
+ }))
+ processsubsup(start)
+ process(accent)
+ stop_tagged()
+ else
+ processsubsup(start)
+ end
+ elseif id == glue_code then
+ -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) }))
+ setattr(start,a_tagged,start_tagged("mspace"))
+ stop_tagged()
+ else
+ setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] }))
+ stop_tagged()
+ end
+ end
+-- showtag(start,id,false)
+ start = getnext(start)
+ end
+ if mtexttag then
+ stop_tagged()
+ end
+end
+
+function noads.handlers.tags(head,style,penalties)
+ start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" })
+ setattr(head,a_tagged,start_tagged("mrow"))
+-- showtag(head,getid(head),true)
+ process(head)
+-- showtag(head,getid(head),false)
+ stop_tagged()
+ stop_tagged()
+end
diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua
index 9267e0f39..41373fcb5 100644
--- a/tex/context/base/mkiv/math-tag.lua
+++ b/tex/context/base/mkiv/math-tag.lua
@@ -52,7 +52,7 @@ local subbox_code = nodecodes.subbox -- attr list
local submlist_code = nodecodes.submlist -- attr list
local mathchar_code = nodecodes.mathchar -- attr fam char
local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
-local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char
+local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char
local style_code = nodecodes.style -- attr style
local choice_code = nodecodes.choice -- attr display text script scriptscript
local fence_code = nodecodes.fence -- attr subtype
@@ -259,7 +259,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
stop_tagged()
-- showtag(start,id,false)
break
- elseif id == delim_code then
+ elseif id == delimiter_code then
-- check for code
setattr(start,a_tagged,start_tagged("mo"))
stop_tagged()
diff --git a/tex/context/base/mkiv/math-toy.mkxl b/tex/context/base/mkiv/math-toy.mkxl
index 4cc65aaa6..510872e3b 100644
--- a/tex/context/base/mkiv/math-toy.mkxl
+++ b/tex/context/base/mkiv/math-toy.mkxl
@@ -27,19 +27,18 @@
%D $\dorecurse{199}{x_{#1} \ifodd#1\relax\Plus\else\Minus\fi} x_{200} \Equal n$ \blank
%D \stoptyping
-\unexpanded\def\definemathtoysymbol
- {\dotripleargument\math_toy_define_symbol}
+\permanent\tolerant\protected\def\definemathtoysymbol[#1]#*[#2]#*[#3]%
+ {\ifarguments\or\or\or
+ \setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}%
+ \fi}
-\def\math_toy_define_symbol[#1][#2][#3]%
- {\setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}}
-
-\unexpanded\def\math_toy_define_symbol_traced#1#2%
+\protected\def\math_toy_define_symbol_traced#1#2%
{\normalexpanded{\discretionary class #1 %
{$\Ustyle\number\mathstyle \darkred #2$}%
{$\Ustyle\number\mathstyle \darkblue #2$}%
{$\Ustyle\number\mathstyle \darkgreen #2$}}}
-\unexpanded\def\math_toy_define_symbol_normal#1#2%
+\protected\def\math_toy_define_symbol_normal#1#2%
{\normalexpanded{\discretionary class #1 %
{$\Ustyle\number\mathstyle #2$}%
{$\Ustyle\number\mathstyle #2$}%
diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua
index 9ee57d80d..c690f3902 100644
--- a/tex/context/base/mkiv/meta-blb.lua
+++ b/tex/context/base/mkiv/meta-blb.lua
@@ -293,7 +293,7 @@ function mp.mf_inject_blob(category,str)
newblob(category,str) -- only for tracing
mp_category = category
mp_str = str
- tex.runtoks("mpblobtext")
+ tex.runlocal("mpblobtext")
end
interfaces.implement {
diff --git a/tex/context/base/mkiv/meta-ini.mkxl b/tex/context/base/mkiv/meta-ini.mkxl
index 28fe09b9e..2ca54a38b 100644
--- a/tex/context/base/mkiv/meta-ini.mkxl
+++ b/tex/context/base/mkiv/meta-ini.mkxl
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+%D Some lmtx upgrading work needs to be done here.
+
% initializations:
%
% - pass settings from tex to mp (delayed expansion)
@@ -87,10 +89,7 @@
%D Anyway, the whole multiple engine mechanism is to keep her gnuplot from
%D interfering.
-\unexpanded\def\startMPdefinitions
- {\dosinglegroupempty\meta_start_definitions}
-
-\def\meta_start_definitions#1#2\stopMPdefinitions
+\permanent\tolerant\protected\def\startMPdefinitions#=#:#2\stopMPdefinitions
{\let\m_meta_saved_instance\currentMPinstance
\edef\currentMPinstance{#1}%
\ifempty\currentMPinstance
@@ -99,65 +98,48 @@
\gtoksapp\t_meta_definitions{#2}%
\let\currentMPinstance\m_meta_saved_instance}
-\let\stopMPdefinitions\relax
-
-\unexpanded\def\startMPextensions
- {\dosinglegroupempty\meta_start_extensions}
+\permanent\let\stopMPdefinitions\relax
-\def\meta_start_extensions#1#2\stopMPextensions % we could use buffers instead
+\permanent\tolerant\protected\def\startMPextensions#=#:#2\stopMPextensions % we could use buffers instead
{\clf_setmpextensions{#1}{#2}}
-\let\stopMPextensions\relax
+\permanent\let\stopMPextensions\relax
-\unexpanded\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled
+\permanent\protected\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled
{\gtoksapp\t_meta_initializations{#1}}
-\let\stopMPinitializations\relax
-
-\unexpanded\def\startMPinclusions
- {\dosingleempty\meta_start_inclusions}
-
-\unexpanded\def\meta_start_inclusions[#1]%
- {\edef\m_meta_option{#1}%
- \dosinglegroupempty\meta_start_inclusions_indeed}
+\permanent\let\stopMPinitializations\relax
-\def\meta_start_inclusions_indeed#1#2\stopMPinclusions
- {\let\m_meta_saved_instance\currentMPinstance
- \edef\currentMPinstance{#1}%
+\permanent\tolerant\protected\def\startMPinclusions[#1]#*#=#:#3\stopMPinclusions
+ {\let\m_meta_saved_instance\currentMPinstance % \pushmacro
+ \edef\currentMPinstance{#2}%
\ifempty\currentMPinstance
\let\currentMPinstance\defaultMPinstance
\fi
- \ifx\m_meta_option\!!plustoken \else
+ \iftok{#1}{+}\else
\global\t_meta_inclusions\emptytoks
\fi
- \gtoksapp\t_meta_inclusions{#2}%
- \let\currentMPinstance\m_meta_saved_instance}
+ \gtoksapp\t_meta_inclusions{#3}%
+ \let\currentMPinstance\m_meta_saved_instance} % \popmacro
-\let\stopMPinclusions\relax
+\permanent\let\stopMPinclusions\relax
% The next was broken since we added instances so it will go away!
-\unexpanded\def\MPinclusions
- {\dosingleempty\meta_inclusions}
-
-\def\meta_inclusions[#1]%
- {\edef\m_meta_option{#1}%
- \dodoublegroupempty\meta_inclusions_indeed}
-
-\def\meta_inclusions_indeed#1#2%
+\permanent\tolerant\protected\def\MPinclusions[#1]#:#*#=#:#*#=%
{\let\m_meta_saved_instance\currentMPinstance
- \ifx\m_meta_option\!!plustoken \else
+ \iftok{#1}{+}\else
\global\t_meta_inclusions\emptytoks
\fi
- \ifsecondargument
- \edef\currentMPinstance{#1}%
- \ifx\currentMPinstance\empty
+ \ifparameter#3\or
+ \edef\currentMPinstance{#2}%
+ \ifempty\currentMPinstance
\let\currentMPinstance\defaultMPinstance
\fi
- \gtoksapp\t_meta_inclusions{#2}%
+ \gtoksapp\t_meta_inclusions{#3}%
\else
\let\currentMPinstance\defaultMPinstance
- \gtoksapp\t_meta_inclusions{#1}%
+ \gtoksapp\t_meta_inclusions{#2}%
\fi
\let\currentMPinstance\m_meta_saved_instance}
@@ -184,7 +166,7 @@
\t_meta_inclusions \emptytoks % in case we redefine
\to \everydefineMPinstance
-\unexpanded\def\resetMPinstance[#1]%
+\permanent\protected\def\resetMPinstance[#1]%
{\writestatus\m!metapost{reset will be implemented when needed}}
\def\meta_analyze_graphicname[#1]%
@@ -201,7 +183,7 @@
{\let\meta_show_properties\meta_show_properties_indeed}
{\let\meta_show_properties\donothing}
-\unexpanded\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance ::
+\protected\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance ::
{\edef\currentMPgraphicname{#2}%
\ifempty\currentMPgraphicname
\edef\currentMPgraphicname{#1}%
@@ -296,7 +278,7 @@
\meta_relocate_graphic
\popMPboundingbox}
-\unexpanded\def\meta_process_graphic_instance#1%
+\protected\def\meta_process_graphic_instance#1%
{\edef\currentMPinstance{#1}%
\ifempty\currentMPinstance
\let\currentMPinstance\defaultMPinstance
@@ -304,7 +286,7 @@
\edef\currentMPformat{\MPinstanceparameter\s!format}%
\meta_process_graphic}
-\unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig
+\protected\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig
{\meta_start_current_graphic
\forgetall
\edef\p_extensions{\MPinstanceparameter\s!extensions}%
@@ -329,7 +311,7 @@
\let\meta_process_graphic_figure_start\relax
\let\meta_process_graphic_figure_stop \relax
-\unexpanded\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages
+\permanent\protected\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages
{\begingroup
\let\normal_meta_process_graphic_start\meta_process_graphic_start
\let\normal_meta_process_graphic_stop \meta_process_graphic_stop
@@ -348,7 +330,7 @@
% \csname\??mpgraphic#1\endcsname ; % ; is safeguard
% \fi}
%
-% \unexpanded\def\meta_enable_include % public
+% \protected\def\meta_enable_include % public
% {\let\meta_handle_use_graphic \thirdofthreearguments
% \let\meta_handle_reusable_graphic\thirdofthreearguments}
%
@@ -363,7 +345,7 @@
% so we cannot overload unless we let back to the original meanings each graphic
% ... a better solution is:
-\def\includeMPgraphic#1% gets expanded !
+\permanent\def\includeMPgraphic#1% gets expanded !
{\ifcsname\??mpgraphic#1\endcsname
\doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard
\fi}
@@ -374,31 +356,31 @@
\newif\ifMPdrawingdone \MPdrawingdonefalse
-\unexpanded\def\finalizeMPdrawing
+\permanent\protected\def\finalizeMPdrawing
{\MPdrawingdonetrue}
\let\MPdrawingdata\empty
-\unexpanded\def\resetMPdrawing
+\permanent\protected\def\resetMPdrawing
{\glet\MPdrawingdata\empty
\global\MPdrawingdonefalse}
-\unexpanded\def\pushMPdrawing
+\permanent\protected\def\pushMPdrawing
{\globalpushmacro\MPdrawingdata
\glet\MPdrawingdata\empty}
-\unexpanded\def\popMPdrawing
+\permanent\protected\def\popMPdrawing
{\globalpopmacro\MPdrawingdata}
-\unexpanded\def\getMPdrawing
+\permanent\protected\def\getMPdrawing
{\ifMPdrawingdone
\expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed?
\fi}
-\def\startMPdrawing
- {\dosingleempty\meta_start_drawing}
+\permanent\tolerant\def\startMPdrawing[#1]% todo: use pickup #:
+ {\meta_start_drawing#1}
-\def\meta_start_drawing[#1]#2\stopMPdrawing % to be redone, this ascii stuff
+\def\meta_start_drawing#1#2\stopMPdrawing % to be redone, this ascii stuff
{\relax
\bgroup
\meta_enable_include
@@ -406,21 +388,21 @@
\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
\egroup}
-\let\stopMPdrawing\relax
+\permanent\let\stopMPdrawing\relax
-\def\MPdrawing#1%
+\permanent\def\MPdrawing#1%
{\relax
\bgroup
\meta_enable_include
\xdef\MPdrawingdata{\MPdrawingdata#1}%
\egroup}
-\unexpanded\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
+\permanent\protected\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
{\setgvalue{\??mpclip#1}{#2}}
-\let\stopMPclip\relax
+\permanent\let\stopMPclip\relax
-\unexpanded\def\meta_grab_clip_path#1#2#3%
+\protected\def\meta_grab_clip_path#1#2#3%
{\begingroup
\d_overlay_width #2\relax
\d_overlay_height#3\relax
@@ -458,7 +440,7 @@
%D Since we want labels to follow the document settings, we also set the font
%D related variables.
-\unexpanded\def\MPfontsizehskip#1%
+\permanent\protected\def\MPfontsizehskip#1%
{\dontleavehmode
\begingroup
\definedfont[#1]%
@@ -509,41 +491,33 @@
\def\meta_prepare_variable_default{\MPcolor{black}} % just to be sure we use a color but ...
-\unexpanded\def\setupMPvariables
- {\dodoubleempty\meta_setup_variables}
-
-\def\meta_setup_variables[#1][#2]%
- {\ifsecondargument
- \getrawparameters[\??graphicvariable#1:][#2]%
- \else
+\permanent\tolerant\protected\def\setupMPvariables[#1]#*[#2]%
+ {\ifarguments
+ \or
\getrawparameters[\??graphicvariable:][#1]%
+ \else
+ \getrawparameters[\??graphicvariable#1:][#2]%
\fi}
-\unexpanded\def\presetMPvariable
- {\dodoubleargument\meta_preset_variable}
-
-\def\meta_preset_variable[#1][#2=#3]%
+\permanent\tolerant\protected\def\presetMPvariable[#1]#*[#2=#3]%
{\ifcsname\??graphicvariable#1:#2\endcsname \else
\setvalue{\??graphicvariable#1:#2}{#3}%
\fi}
-\def\MPrawvar#1#2% no checking
+\permanent\def\MPrawvar#1#2% no checking
{\begincsname\??graphicvariable#1:#2\endcsname}
-\def\MPvariable#1% todo: could be a framed chain
+\permanent\def\MPvariable#1% todo: could be a framed chain
{\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname}
-\unexpanded\def\useMPvariables
- {\dodoubleargument\meta_use_variables}
-
-\def\meta_use_variables[#1][#2]%
+\permanent\tolerant\protected\def\useMPvariables[#1]#*[#2]%
{\edef\currentmpvariableclass{#1}%
\meta_prepare_variables{#2}}
-\unexpanded\def\meta_prepare_variables#1%
+\protected\def\meta_prepare_variables#1%
{\processcommalist[#1]\meta_prepare_variable}
-\unexpanded\def\meta_prepare_variable#1%
+\protected\def\meta_prepare_variable#1%
{\edef\m_meta_current_variable_template
{\??graphicvariable\currentmpvariableclass:#1}%
\edef\m_meta_current_variable
@@ -554,10 +528,10 @@
\expandafter\meta_prepare_variable_yes
\fi}
-\unexpanded\def\meta_prepare_instance_variables
+\protected\def\meta_prepare_instance_variables
{\expandafter\processcommalist\expandafter[\m_meta_instance_variables]\meta_prepare_instance_variable}
-\unexpanded\def\meta_prepare_instance_variable#1%
+\protected\def\meta_prepare_instance_variable#1%
{\edef\m_meta_current_variable_template
{\??graphicvariable\currentmpvariableclass:#1}%
\edef\m_meta_current_variable
@@ -617,6 +591,8 @@
%D \stopuniqueMPgraphic
%D \stoptyping
+% todo: frozen or not?
+
\def\overlaystamp % watch the \MPcolor, since colors can be redefined
{\the\d_overlay_width :%
\the\d_overlay_height :%
@@ -647,39 +623,39 @@
% hm, isn't this already done elsewhere?
-\unexpanded\def\meta_obey_box_depth
+\protected\def\meta_obey_box_depth
{\setbox\b_meta_graphic\hpack\bgroup
\raise\MPlly\box\b_meta_graphic
\egroup}
-\unexpanded\def\meta_ignore_box_depth
+\protected\def\meta_ignore_box_depth
{\normalexpanded
- {\meta_obey_box_depth % hence the \unexpanded
+ {\meta_obey_box_depth % hence the \protected
\wd\b_meta_graphic\the\wd\b_meta_graphic
\ht\b_meta_graphic\the\ht\b_meta_graphic
\dp\b_meta_graphic\the\dp\b_meta_graphic}}
-\unexpanded\def\meta_obey_box_origin
+\protected\def\meta_obey_box_origin
{\setbox\b_meta_graphic\hpack\bgroup
\kern\MPllx\raise\MPlly\box\b_meta_graphic
\egroup}
-\unexpanded\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth}
-\unexpanded\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth}
-\unexpanded\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin}
-\unexpanded\def\normalMPboxdepth{\let\meta_relocate_box\relax}
+\permanent\protected\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth}
+\permanent\protected\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth}
+\permanent\protected\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin}
+\permanent\protected\def\normalMPboxdepth{\let\meta_relocate_box\relax}
\let\meta_relocate_box\relax
-\unexpanded\def\meta_place_graphic % the converter also displaces so in fact we revert
+\protected\def\meta_place_graphic % the converter also displaces so in fact we revert
{\meta_relocate_box
\box\b_meta_graphic}
-\unexpanded\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens
+\protected\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens
{\MPllx#2\MPlly#3\MPurx#4\MPury#5%
\hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
-\unexpanded\def\meta_use_box
+\protected\def\meta_use_box
{\setunreferencedobject{MP}}
\def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although,
@@ -697,21 +673,20 @@
\fi
\endgroup}
-\unexpanded\def\startuniqueMPgraphic
+% todo: we partially expand
+
+\protected\def\startuniqueMPgraphic
{\dodoublegroupempty\meta_start_unique_graphic}
-\let\stopuniqueMPgraphic\relax
+\permanent\let\stopuniqueMPgraphic\relax
\def\meta_start_unique_graphic#1%
{\normalexpanded{\meta_start_unique_graphic_indeed{#1}}}
-\unexpanded\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic
+\permanent\protected\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic
{\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}}
-\unexpanded\def\uniqueMPgraphic
- {\dodoublegroupempty\meta_unique_graphic}
-
-\def\meta_unique_graphic#1#2%
+\permanent\tolerant\protected\def\uniqueMPgraphic#=#*#=%
{\meta_begin_graphic_group{#1}%
\setupMPvariables[#1][#2]%
\begincsname\??mpgraphic#1\endcsname\empty
@@ -728,26 +703,26 @@
\meta_process_graphic{#3}%
\endgroup}
-\unexpanded\def\startuseMPgraphic
+\permanent\protected\def\startuseMPgraphic % todo, modernize
{\dodoublegroupempty\meta_start_use_graphic}
-\let\stopuseMPgraphic\relax
+\permanent\let\stopuseMPgraphic\relax
\def\meta_start_use_graphic#1%
{\normalexpanded{\meta_start_use_graphic_indeed{#1}}}
-\unexpanded\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic
+\protected\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic
{\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
-\unexpanded\def\startusableMPgraphic % redundant but handy
+\permanent\protected\def\startusableMPgraphic % redundant but handy % todo, modernize
{\dodoublegroupempty\meta_start_usable_graphic}
-\let\stopusableMPgraphic\relax
+\permanent\let\stopusableMPgraphic\relax
\def\meta_start_usable_graphic#1%
{\normalexpanded{\meta_start_usable_graphic_indeed{#1}}}
-\unexpanded\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic
+\protected\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic
{\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
\def\meta_handle_reusable_graphic#1#2#3%
@@ -764,21 +739,18 @@
\csname\??mpgraphic#1\endcsname\empty
\endgroup}
-\unexpanded\def\startreusableMPgraphic
+\permanent\protected\def\startreusableMPgraphic % todo, modernize
{\dodoublegroupempty\meta_start_reusable_graphic}
-\let\stopreusableMPgraphic\relax
+\permanent\let\stopreusableMPgraphic\relax
\def\meta_start_reusable_graphic#1%
{\normalexpanded{\meta_start_reusable_graphic_indeed{#1}}}
-\unexpanded\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic
+\protected\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic
{\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}}
-\unexpanded\def\useMPgraphic
- {\dodoublegroupempty\meta_use_graphic}
-
-\def\meta_use_graphic#1#2%
+\permanent\tolerant\protected\def\useMPgraphic#=#*#=%
{\meta_begin_graphic_group{#1}%
\ifcsname\??mpgraphic#1\endcsname
\edef\usedMPgraphicname{#1}%
@@ -795,8 +767,8 @@
\fi
\meta_end_graphic_group}
-\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
-\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed
+\aliased\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
+\aliased\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed
%D \macros
%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
@@ -815,22 +787,19 @@
\MPcolor\overlaycolor :%
\MPcolor\overlaylinecolor}
-\unexpanded\def\startuniqueMPpagegraphic
+\permanent\tolerant\protected\def\startuniqueMPpagegraphic % todo the modern way
{\dodoublegroupempty\meta_start_unique_page_graphic}
-\let\stopuniqueMPpagegraphic\relax
+\permanent\let\stopuniqueMPpagegraphic\relax
\def\meta_start_unique_page_graphic#1%
{\normalexpanded{\meta_start_unique_page_graphic_indeed{#1}}}
-\unexpanded\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage
- {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state
- \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined
+\protected\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage
+ {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state
+ \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined
-\unexpanded\def\uniqueMPpagegraphic
- {\dodoublegroupempty\meta_unique_page_graphic}
-
-\def\meta_unique_page_graphic#1#2%
+\permanent\tolerant\protected\def\uniqueMPpagegraphic#=#=%
{\meta_begin_graphic_group{#1}%
\let\overlaystamp\overlaypagestamp
\setupMPvariables[\m_meta_page_prefix:#1][#2]% prefix is new here
@@ -849,36 +818,30 @@
%D Since we need to feed \METAPOST\ with expanded dimensions, we introduce a
%D dedicated expansion engine. We redefine \type {\extendMPoverlaystamp} to
-\unexpanded\def\extendMPoverlaystamp#1%
+\permanent\protected\def\extendMPoverlaystamp#1%
{\processcommalist[#1]\meta_extend_overlay_stamp}
\def\meta_extend_overlay_stamp#1%
{\meta_prepare_instance_variable{#1}%
\edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
-\unexpanded\def\getMPdata {\clf_getMPdata}
- \let\rawMPdata \clf_getMPdata
+\permanent\protected\def\getMPdata {\clf_getMPdata}
+ \let\rawMPdata \clf_getMPdata % we need frozen at the lua end
-\unexpanded\def\getMPstored{\clf_getMPstored}
- \let\rawMPstored \clf_getMPstored
+\permanent\protected\def\getMPstored{\clf_getMPstored}
+ \let\rawMPstored \clf_getMPstored % we need frozen at the lua end
%D We need this trick because we need to make sure that the tex scanner sees
%D newlines and does not quit. Also, we do need to flush the buffer under a normal
%D catcode regime in order to expand embedded tex macros. As usual with buffers,
%D \type {#1} can be a list.
-\unexpanded\def\processMPbuffer
- {\dosingleempty\meta_process_buffer}
-
-\def\meta_process_buffer[#1]%
+\permanent\tolerant\protected\def\processMPbuffer[#1]%
{\meta_begin_graphic_group{#1}%
\meta_process_graphic{\clf_feedback{\currentMPgraphicname}}%
\meta_end_graphic_group}
-\unexpanded\def\runMPbuffer
- {\dosingleempty\meta_run_buffer}
-
-\def\meta_run_buffer[#1]% processing only
+\permanent\tolerant\protected\def\runMPbuffer[#1]%
{\startnointerference\meta_process_buffer[#1]\stopnointerference}
%D \macros
@@ -887,12 +850,12 @@
%D In order to synchronize the main \TEX\ run and the runs local to \METAPOST,
%D environments can be passed.
-\unexpanded\def\startMPenvironment
+\protected\def\startMPenvironment
{\begingroup
- \catcode\endoflineasciicode \ignorecatcode
- \dosingleempty\meta_start_environment}
+ \catcode\endoflineasciicode\ignorecatcode
+ \meta_start_environment}
-\def\meta_start_environment[#1]#2\stopMPenvironment
+\tolerant\def\meta_start_environment[#1]#:#2\stopMPenvironment
{\endgroup
\edef\m_meta_option{#1}
\ifx\m_meta_option\s!reset
@@ -904,12 +867,12 @@
\fi
\clf_mptexset{\detokenize{#2}}}
-\let\stopMPenvironment\relax
+\permanent\let\stopMPenvironment\relax
-\unexpanded\def\resetMPenvironment
+\protected\def\resetMPenvironment
{\clf_mptexreset}
-\unexpanded\def\useMPenvironmentbuffer[#1]%
+\protected\def\useMPenvironmentbuffer[#1]%
{\clf_mptexsetfrombuffer{#1}}
%D This command takes \type {[reset]} as optional argument.
@@ -926,56 +889,35 @@
%D
%D The most simple case:
-\unexpanded\def\startMPcode
- {\dosinglegroupempty\meta_start_code}
-
-\let\stopMPcode\relax
-
-\def\meta_start_code
- {\iffirstargument
- \expandafter\meta_start_code_instance
- \else
- \expandafter\meta_start_code_standard
- \fi}
-
-\def\meta_start_code_instance#1#2\stopMPcode
+\permanent\tolerant\protected\def\startMPcode#=#:#2\stopMPcode
{\begingroup
\edef\currentMPinstance{#1}%
+ \ifempty\currentMPinstance
+ \let\currentMPinstance\defaultMPinstance
+ \fi
\let\currentMPgraphicname\empty
\edef\currentMPformat{\MPinstanceparameter\s!format}%
\meta_enable_include
\meta_process_graphic{#2}%
\endgroup}
-\def\meta_start_code_standard#1#2\stopMPcode
- {\begingroup
- \let\currentMPinstance\defaultMPinstance
- \let\currentMPgraphicname\empty
- \edef\currentMPformat{\MPinstanceparameter\s!format}%
- \meta_process_graphic{#2}%
- \endgroup}
+\permanent\let\stopMPcode\relax
-\unexpanded\def\MPcode
- {\dodoublegroupempty\meta_code}
+%D This one is not optimized because it's only used for small snippets, if it
+%D is used at all.
-\def\meta_code
- {\ifsecondargument
- \expandafter\meta_code_instance
+\permanent\tolerant\protected\def\MPcode#=#:#*#=%
+ {\ifparameter#1\or
+ \meta_begin_graphic_group{#1}%
+ \meta_enable_include
+ \meta_process_graphic{#2}%
+ \meta_end_graphic_group
\else
- \expandafter\meta_code_standard
+ \let\currentMPinstance\defaultMPinstance
+ \meta_enable_include
+ \meta_process_graphic{#1}%
\fi}
-\def\meta_code_instance#1#2%
- {\meta_begin_graphic_group{#1}%
- \meta_enable_include
- \meta_process_graphic{#2}%
- \meta_end_graphic_group}
-
-\def\meta_code_standard#1#2%
- {\let\currentMPinstance\defaultMPinstance
- \meta_enable_include
- \meta_process_graphic{#1}}
-
% a bit nasty (also needed for compatibility:
% \startMPrun input mp-www.mp ; \stopMPrun
@@ -986,25 +928,16 @@
\let\MPruninstance\defaultMPinstance
-\unexpanded\def\useMPrun#1#2% name n
+\permanent\protected\def\useMPrun#1#2% name n
{\begingroup
\def\MPaskedfigure{#2}%
- \doifelsenothing{#1}
- {\useMPgraphic{mprun}}%
- {\useMPgraphic{#1}}%
+ \normalexpanded{\useMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}%
\endgroup}
-\unexpanded\def\startMPrun
- {\dosinglegroupempty\meta_start_run}
-
-\def\meta_start_run#1#2\stopMPrun
- {\iffirstargument
- \startuseMPgraphic{#1}#2\stopuseMPgraphic
- \else
- \startuseMPgraphic{mprun}#2\stopuseMPgraphic
- \fi}
+\permanent\tolerant\protected\def\startMPrun#=#:#2\stopMPrun
+ {\normalexpanded{\startuseMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}#2\stopuseMPgraphic}
-\let\stopMPrun\relax
+\permanent\let\stopMPrun\relax
%D The \type {\resetMPenvironment} is a quick way to erase
%D the token list.
@@ -1031,7 +964,7 @@
%D Loading specific \METAPOST\ related definitions is
%D accomplished by:
-\unexpanded\def\useMPlibrary[#1]{\clf_useMPlibrary{#1}}
+\permanent\protected\def\useMPlibrary[#1]{\clf_useMPlibrary{#1}}
%D \macros
%D {setMPtext, MPtext, MPstring, MPbetex}
@@ -1048,13 +981,13 @@
\installcorenamespace{mptext}
-\unexpanded\def\setMPtext#1#2% todo : #1 must be made : safe
- {\defconvertedargument\ascii{#2}%
+\permanent\protected\def\setMPtext#1#2% todo : #1 must be made : safe
+ {\defconvertedargument\ascii{#2}% hm, kind of old fashioned, this
\dodoglobal\letvalue{\??mptext#1}\ascii}
-\def\MPtext #1{\begincsname\??mptext#1\endcsname\empty}
-\def\MPstring#1{"\begincsname\??mptext#1\endcsname\empty"}
-\def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex}
+\permanent\def\MPtext #1{\begincsname\??mptext#1\endcsname\empty}
+\permanent\def\MPstring#1{"\begincsname\??mptext#1\endcsname\empty"}
+\permanent\def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex}
%D In order to communicate conveniently with the \TEX\ engine, we introduce some
%D typesetting variables.
@@ -1139,11 +1072,11 @@
\to \everyMPgraphic
\appendtoks
- \let \# \letterhash
- \let \_ \letterunderscore
- \let \& \letterampersand
- \let \{ \letteropenbrace
- \let \} \letterclosebrace
+ \enforced\let\#\letterhash
+ \enforced\let\_\letterunderscore
+ \enforced\let\&\letterampersand
+ \enforced\let\{\letteropenbrace
+ \enforced\let\}\letterclosebrace
\to \everyMPgraphic
%D \macros
@@ -1205,7 +1138,7 @@
%D You won't believe me if I tell you what funny side effects can occur. One took me
%D over a day to uncover when processing the screen version of the \METAFUN\ manual.
-\def\doifelseMPgraphic#1%
+\permanent\def\doifelseMPgraphic#1%
{\ifcsname\??mpgraphic #1\endcsname\expandafter\firstoftwoarguments \orelse
\ifcsname\??mpgraphic o:#1\endcsname\expandafter\firstoftwoarguments \orelse
\ifcsname\??mpgraphic e:#1\endcsname\expandafter\firstoftwoarguments \else
@@ -1285,22 +1218,16 @@
%D
%D \typebuffer \getbuffer
-\unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure
+\permanent\protected\def\startstaticMPfigure#1#2\stopstaticMPfigure
{\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic}
-\unexpanded\def\startstaticMPgraphic
- {\dodoublegroupempty\meta_start_static_graphic}
-
-\def\meta_start_static_graphic#1#2#3\stopstaticMPgraphic
+\permanent\tolerant\protected\def\startstaticMPgraphic#=#:#=#:#3\stopstaticMPgraphic
{\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic}
-\let\stopstaticMPfigure \relax
-\let\stopstaticMPgraphic\relax
-
-\unexpanded\def\usestaticMPfigure
- {\dodoubleempty\meta_use_static_figure}
+\permanent\let\stopstaticMPfigure \relax
+\permanent\let\stopstaticMPgraphic\relax
-\def\meta_use_static_figure[#1][#2]%
+\permanent\tolerant\protected\def\usestaticMPfigure[#1]#*[#2]%
{\ifsecondargument
\scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}%
\else
@@ -1309,8 +1236,8 @@
%D Goody for preventing overflows:
-%def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}
-\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax}
+%frozen\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}
+\permanent\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax}
%D There is no way to distinguish the black color that you get when you issue a
%D \type {draw} without color specification from a color that has an explicit black
@@ -1384,9 +1311,9 @@
%D $(x,y) = (\MPrunset{point}{,})$
%D \stoptyping
-\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar
-\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number
-\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset
+\permanent\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar
+\permanent\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number
+\permanent\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset
\prependtoks \clf_mppushvariables \to \everybeforepagebody
\appendtoks \clf_mppopvariables \to \everyafterpagebody
@@ -1396,22 +1323,13 @@
%D We also provide an outputless run:
-\unexpanded\def\startMPcalculation
+\permanent\tolerant\protected\def\startMPcalculation#=#:#2\stopMPcalculation
{\begingroup
\setbox\nextbox\hpack\bgroup
- \dosinglegroupempty\meta_start_calculation}
-
-\let\stopMPcalculation\relax
-
-\def\meta_start_calculation
- {\iffirstargument
- \expandafter\meta_start_calculation_instance
- \else
- \expandafter\meta_start_calculation_standard
- \fi}
-
-\def\meta_start_calculation_instance#1#2\stopMPcalculation
- {\edef\currentMPinstance{#1}%
+ \edef\currentMPinstance{#1}%
+ \ifempty\currentMPinstance
+ \let\currentMPinstance\defaultMPinstance
+ \fi
\let\currentMPgraphicname\empty
\edef\currentMPformat{\MPinstanceparameter\s!format}%
\meta_enable_include
@@ -1419,13 +1337,7 @@
\egroup
\endgroup}
-\def\meta_start_calculation_standard#1#2\stopMPcalculation
- {\let\currentMPinstance\defaultMPinstance
- \let\currentMPgraphicname\empty
- \edef\currentMPformat{\MPinstanceparameter\s!format}%
- \meta_process_graphic{#2;draw origin}%
- \egroup
- \endgroup}
+\permanent\let\stopMPcalculation\relax
%D \macros
%D {setupMPgraphics}
@@ -1466,9 +1378,9 @@
%D Some more helpers (see \type {meta-grd.mkiv} for an example of usage):
-\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty}
-\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty}
-\def\MPspar#1#2{"#1#2"}
+\permanent\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty}
+\permanent\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty}
+\permanent\def\MPspar#1#2{"#1#2"}
%D Done.
diff --git a/tex/context/base/mkiv/meta-mac.mkxl b/tex/context/base/mkiv/meta-mac.mkxl
index 7ced2aff9..76b7396ae 100644
--- a/tex/context/base/mkiv/meta-mac.mkxl
+++ b/tex/context/base/mkiv/meta-mac.mkxl
@@ -13,40 +13,16 @@
\unprotect
-\unexpanded\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}}
-\unexpanded\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}}
-\unexpanded\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}}
+\permanent\protected\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}}
+\permanent\protected\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}}
+\permanent\protected\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}}
-% \unexpanded\def\useMPgraphic
-% {\doifnextoptionalelse\meta_use_MP_graphic_yes\meta_use_MP_graphic_nop}
-
-% \def\meta_use_MP_graphic_nop
-% {\dodoublegroupempty\meta_use_graphic}
-
-% \def\meta_use_MP_graphic_yes
-% {\dodoubleempty\meta_use_graphic_new}
-
-% \def\meta_use_graphic_new[#1][#2]%
-% {\begingroup
-% % If really needed weh can use grouplevel but normally these graphics are
-% % not nested.
-% \clf_lmt_parameters_preset{#1}[#2]%
-% \meta_use_graphic{#1}{}%
-% \clf_lmt_parameters_reset{#1}%
-% \endgroup}
-
-\unexpanded\def\useMPmacro
- {\dotripleempty\meta_use_macro}
-
-\def\meta_use_macro[#1][#2][#3]%
- {\ifthirdargument
- \meta_begin_graphic_group{#1}%
+\permanent\tolerant\protected\def\useMPmacro[#1]#*[#2]#*[#3]%
+ {\ifarguments\or
+ \let\currentMPinstance\defaultMPinstance
\meta_enable_include
- \clf_lmt_parameters_preset{#2}[#3]%
- \meta_process_graphic{lmt_#2;}%
- \clf_lmt_parameters_reset{#2}%
- \meta_end_graphic_group
- \orelse\ifsecondargument
+ \meta_process_graphic{lmt_#1;}%
+ \or
\doifelseassignment{#2}
{\let\currentMPinstance\defaultMPinstance
\meta_enable_include
@@ -57,10 +33,13 @@
\meta_enable_include
\meta_process_graphic{lmt_#1;}%
\meta_end_graphic_group}%
- \else
- \let\currentMPinstance\defaultMPinstance
+ \or
+ \meta_begin_graphic_group{#1}%
\meta_enable_include
- \meta_process_graphic{lmt_#1;}%
+ \clf_lmt_parameters_preset{#2}[#3]%
+ \meta_process_graphic{lmt_#2;}%
+ \clf_lmt_parameters_reset{#2}%
+ \meta_end_graphic_group
\fi}
\protect
diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua
index 3945ffcfe..e737b5d86 100644
--- a/tex/context/base/mkiv/mlib-pdf.lua
+++ b/tex/context/base/mkiv/mlib-pdf.lua
@@ -363,18 +363,20 @@ end
local stack = { }
local function pushproperties(figure)
+ -- maybe there will be getters in lmtx
local boundingbox = figure:boundingbox()
+ local slot = figure:charcode() or 0
local properties = {
llx = boundingbox[1],
lly = boundingbox[2],
urx = boundingbox[3],
ury = boundingbox[4],
- slot = figure:charcode(),
+ slot = slot,
width = figure:width(),
height = figure:height(),
depth = figure:depth(),
- italic = figure:italcorr(),
- number = figure:charcode() or 0,
+ italic = figure:italcorr(), -- figure:italic() in lmtx
+ number = slot,
}
insert(stack,properties)
metapost.properties = properties
diff --git a/tex/context/base/mkiv/mlib-pdf.mkxl b/tex/context/base/mkiv/mlib-pdf.mkxl
index 763e7ecdd..90a5b5a86 100644
--- a/tex/context/base/mkiv/mlib-pdf.mkxl
+++ b/tex/context/base/mkiv/mlib-pdf.mkxl
@@ -30,7 +30,7 @@
\ifdefined\MPbox \else \newbox \MPbox \fi
-\unexpanded\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points
+\permanent\protected\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points
{\global\MPllx #1\onebasepoint
\global\MPlly #2\onebasepoint
\global\MPurx #3\onebasepoint
@@ -38,7 +38,7 @@
\global\MPwidth \dimexpr\MPurx-\MPllx\relax
\global\MPheight\dimexpr\MPury-\MPlly\relax}
-\unexpanded\def\resetMPboundingbox
+\permanent\protected\def\resetMPboundingbox
{\global\MPwidth \zeropoint
\global\MPheight\zeropoint
\global\MPllx \zeropoint
@@ -48,8 +48,8 @@
\let\popMPboundingbox\relax
-\unexpanded\def\pushMPboundingbox
- {\edef\popMPboundingbox
+\permanent\protected\def\pushMPboundingbox
+ {\enforced\permanent\protected\edef\popMPboundingbox
{\global\MPwidth \the\MPwidth
\global\MPheight\the\MPheight
\global\MPllx \the\MPllx
@@ -60,14 +60,14 @@
% we need to combine these
-\unexpanded\def\repositionMPboxindeed
+\permanent\protected\def\repositionMPboxindeed
{\setbox\MPbox\hpack\bgroup
\kern-\MPllx
\raise-\MPlly
\box\MPbox
\egroup}
-\unexpanded\def\repositionMPbox
+\permanent\protected\def\repositionMPbox
{\ifzeropt\MPllx
\ifzeropt\MPlly
% okay
@@ -78,20 +78,9 @@
\repositionMPboxindeed
\fi}
-\unexpanded\def\finalizeMPbox
- {\repositionMPbox
- \setbox\MPbox\vpack to \MPheight\bgroup
- \vfill
- \hsize\MPwidth
- \smashbox\MPbox
- \box\MPbox
- \egroup
- \wd\MPbox\MPwidth
- \ht\MPbox\MPheight}
-
% combined
-\unexpanded\def\finalizeMPbox
+\permanent\protected\def\finalizeMPbox
{\boxxoffset\MPbox-\MPllx\relax
\boxyoffset\MPbox\dimexpr\boxyoffset\MPbox-\MPheight-\MPlly\relax
\wd\MPbox\MPwidth
@@ -99,9 +88,9 @@
% MPLIB specific:
-\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded
+\permanent\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded
-\unexpanded\def\startMPLIBtoPDF#1#2#3#4%
+\permanent\protected\def\startMPLIBtoPDF#1#2#3#4%
{\meta_process_graphic_figure_start
\dostarttagged\t!mpgraphic\empty
\naturalhpack attr \imageattribute \plusone \bgroup
@@ -111,7 +100,7 @@
% \forgetall % already done elsewhere
\noindent} % forces the proper cm in the backend
-\unexpanded\def\stopMPLIBtoPDF
+\permanent\protected\def\stopMPLIBtoPDF
{\egroup
\finalizeMPbox
\box\MPbox
@@ -119,7 +108,7 @@
\dostoptagged
\meta_process_graphic_figure_stop}
-\def\MPLIBflushreset % This can (will) move to the Lua end.
+\permanent\protected\def\MPLIBflushreset % This can (will) move to the Lua end.
{\clf_mpflushreset}
%D Kind of special:
@@ -136,19 +125,21 @@
% \directMPgraphic{input "test.mp" ;}
% \stoptext
-\let\normalstartMPLIBtoPDF\startMPLIBtoPDF
-\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF
+\aliased\let\normalstartMPLIBtoPDF\startMPLIBtoPDF
+\aliased\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF
+
+\permanent\protected\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF}
+\permanent\protected\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage}
-\unexpanded\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF}
-\unexpanded\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage}
+% can become \permanent\protected\def\directMPgraphic#=#*#=% but best test first
-\unexpanded\def\directMPgraphic
+\permanent\protected\def\directMPgraphic
{\dodoublegroupempty\mlib_direct_graphic}
\def\mlib_direct_graphic#1#2% makes pages (todo: make boxes)
{\meta_begin_graphic_group{#1}%
- \let\startMPLIBtoPDF\directstartMPLIBtoPDF
- \let\stopMPLIBtoPDF \directstopMPLIBtoPDF
+ \enforced\let\startMPLIBtoPDF\directstartMPLIBtoPDF
+ \enforced\let\stopMPLIBtoPDF \directstopMPLIBtoPDF
\meta_start_current_graphic
\forgetall
\edef\p_extensions{\MPinstanceparameter\s!extensions}%
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index e34bfe5f9..140acd185 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -25,7 +25,7 @@ local setmacro = interfaces.setmacro
local texsetbox = tex.setbox
local textakebox = tex.takebox -- or: nodes.takebox
-local texruntoks = tex.runtoks
+local texrunlocal = tex.runlocal
local copy_list = node.copy_list
local flush_list = node.flush_list
local setmetatableindex = table.setmetatableindex
@@ -858,7 +858,7 @@ local tx_reset, tx_process do
mp_t = nil
top.texstrings[mp_index] = str
top.texregimes[mp_index] = regime or -1
- texruntoks("mptexttoks")
+ texrunlocal("mptexttoks")
local box = textakebox("mptextbox")
top.textexts[mp_target] = box
mp.triplet(bp*box.width,bp*box.height,bp*box.depth)
@@ -922,7 +922,7 @@ local tx_reset, tx_process do
if overload then
top.texstrings[mp_index] = map.template or map.label or "error"
top.texregimes[mp_index] = regime or -1
- texruntoks("mptexttoks")
+ texrunlocal("mptexttoks")
local box = textakebox("mptextbox") or new_hlist()
width = bp * box.width
where = overload.where
@@ -930,7 +930,7 @@ local tx_reset, tx_process do
-- the real text
top.texstrings[mp_index] = overload and overload.text or text or "error"
top.texregimes[mp_index] = regime or -1
- texruntoks("mptexttoks")
+ texrunlocal("mptexttoks")
local box = textakebox("mptextbox") or new_hlist()
local twd = bp * box.width
local tht = bp * box.height
@@ -1047,7 +1047,7 @@ local tx_reset, tx_process do
local mp_hash = prescript.tx_cache
local box
if mp_hash == "no" then
- texruntoks("mptexttoks")
+ texrunlocal("mptexttoks")
box = textakebox("mptextbox")
else
local cache = data.texhash
@@ -1080,7 +1080,7 @@ local tx_reset, tx_process do
if box then
box = copy_list(box)
else
- texruntoks("mptexttoks")
+ texrunlocal("mptexttoks")
box = textakebox("mptextbox")
cache[mp_hash] = box
end
@@ -1163,7 +1163,7 @@ local gt_reset, gt_process do
if not graphics[index] then
mp_index = index
mp_str = str
- texruntoks("mpgraphictexttoks")
+ texrunlocal("mpgraphictexttoks")
end
end
@@ -1584,7 +1584,7 @@ local ot_reset, ot_process do
mp_index = index
mp_kind = kind
mp_str = str
- texruntoks("mpoutlinetoks")
+ texrunlocal("mpoutlinetoks")
end
end
diff --git a/tex/context/base/mkiv/mult-aux.mkxl b/tex/context/base/mkiv/mult-aux.mkxl
index 1df5bcf24..c1c99edbd 100644
--- a/tex/context/base/mkiv/mult-aux.mkxl
+++ b/tex/context/base/mkiv/mult-aux.mkxl
@@ -21,7 +21,7 @@
\unprotect
-\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % hex 19
+\immutable\edef\??empty{\Uchar25} \immutable\letvalue{\Uchar25}\empty % hex 19
% \edef\s!parent{\Uchar29} % inlining  is ugly, a tiny bit faster, but neglectable on a run
@@ -174,26 +174,17 @@
\let\m_mult_interfaces_namespace\empty
-\def\mult_interfaces_get_parameters#1[#2%
- {\if\noexpand#2]%
- \expandafter\gobbleoneargument
- \else
- \def\m_mult_interfaces_namespace{#1}%
- \expandafter\mult_interfaces_get_parameters_indeed
- \fi#2}
+\def\mult_interfaces_get_parameters#1[%
+ {\def\m_mult_interfaces_namespace{#1}%
+ \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed}
-\def\mult_interfaces_get_parameters_indeed#1]% namespace already set
+\def\mult_interfaces_get_parameters_indeed#1]%
{\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments}
-\def\mult_interfaces_get_parameters_item_next
- {\expandafterspaces\mult_interfaces_get_parameters_item}
-
-\def\mult_interfaces_get_parameters_item#1,%
- {\ifarguments
- % done
- \else
+\def\mult_interfaces_get_parameters_item#*#1,%
+ {\ifarguments \else
\mult_interfaces_get_parameters_item_okay#1,\ignorearguments
- \expandafter\mult_interfaces_get_parameters_item_next
+ \expandafter\mult_interfaces_get_parameters_item
\fi}
\def\mult_interfaces_get_parameters_item_okay#1=#2,%
@@ -219,25 +210,16 @@
\or
\mult_interfaces_get_parameters_item_error
\else
- \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}%
+ \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}%
\fi}
-% \def\mult_interfaces_get_parameters_item_error#0\csname#2#3\endcsname#0%
-% {\if,#3\else\mult_interfaces_get_parameters_error_indeed{#2}{#3}\fi}
-
- \def\mult_interfaces_get_parameters_item_error#-\csname#1#2\endcsname#-%
+ \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-%
{\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi}
\stopinterface
%D Used?
-% \def\mult_check_for_assignment_indeed#0=#2#0^^^^0004%
-% {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi}
-%
-% \def\mult_check_for_assignment_indeed_begin_#0=#2#0^^^^0004%
-% {\if#2^^^^0003}
-
\def\mult_check_for_assignment_indeed#-=#1#-^^^^0004%
{\if#1^^^^0003\assignmentfalse\else\assignmenttrue\fi}
@@ -258,20 +240,13 @@
%D and that only the high level setup commands are used with language specific
%D interfaces.
-% \protected\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
-% \protected\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
-% \protected\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
-% \protected\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
-% \protected\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
-% \protected\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
-
% \startinterface english
- \protected\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname}
- \protected\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty}
- \protected\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname}
- \protected\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname}
- \protected\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname}
- \protected\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname}
+ \protected\def\mult_interfaces_let #1#2{\letcsname#1#2\endcsname}
+ \protected\def\mult_interfaces_lete#1#2{\letcsname#1#2\endcsname\empty}
+ \protected\def\mult_interfaces_def #1#2{\defcsname#1#2\endcsname}
+ \protected\def\mult_interfaces_edef#1#2{\edefcsname#1#2\endcsname}
+ \protected\def\mult_interfaces_gdef#1#2{\globaldef\csname#1#2\endcsname}
+ \protected\def\mult_interfaces_xdef#1#2{\globaledef\csname#1#2\endcsname}
% \stopinterface
%D Do, we only interface the assignment definition:
@@ -279,7 +254,7 @@
\protected\def\mult_interfaces_adef#1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
\startinterface english
- \protected\def\mult_interfaces_adef#1#2{\expandafter \def\csname#1#2\endcsname}
+ \protected\def\mult_interfaces_adef#1#2{\defcsname#1#2\endcsname}
\stopinterface
% the commented detokenized variant that backtracks ... needs testing usage first
@@ -299,19 +274,17 @@
\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
\protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only)
- {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
- \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
- \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
- %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
- %\def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ?
- %\def#5##1##2{\ifx##1\relax^^^^0019\else#4##1{##2}\fi}% is {} needed around ##1 ?
- \edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ?
- \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
- \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
- \def#8##1{\begincsname#1#2:##1\endcsname}
- \def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}}
-
-\protected\def\installparameterhandler#1#2%
+ {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
+ \frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
+ \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ \frozen\edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ?
+ \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
+ \frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
+ \frozen\def#8##1{\begincsname#1#2:##1\endcsname}%
+ % TODO
+ \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}}
+
+\permanent\protected\def\installparameterhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_parameter_handler
{\noexpand#1}% \??aa
@@ -325,10 +298,10 @@
\expandafter\noexpand\csname letfrom#2parameter\endcsname}} % strict#2parameter is gone
\protected\def\mult_interfaces_install_root_parameter_handler#1#2#3%
- {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
- \def#3##1{\begincsname#1:##1\endcsname}}
+ {\frozen\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
+ \frozen\def#3##1{\begincsname#1:##1\endcsname}}
-\protected\def\installrootparameterhandler#1#2%
+\permanent\protected\def\installrootparameterhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_root_parameter_handler
{\noexpand#1}% \??aa
@@ -337,18 +310,17 @@
\protected\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
{\ifx#2\relax\let#2\empty\fi
- \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
- \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
- %\def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
- \def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}%
- \def#6{#1#2:}%
- \def#7##1{#1##1:}%
- %\def#8{\ifx#2\empty\orelse\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi}%
- \def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi}%
- \protected\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}
-
-\protected\def\installparameterhashhandler#1#2%
- {\expandafter\let\csname#2namespace\endcsname#1%
+ \frozen\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
+ \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
+ \frozen\def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}%
+ \frozen\def#6{#1#2:}%
+ \frozen\def#7##1{#1##1:}%
+ \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname#1#2:\s!parent\endcsname#1\fi}%
+ \frozen\protected\def#9##1{\edefcsname#1##1:\s!parent\endcsname{#1#2}}}
+
+\permanent\protected\def\installparameterhashhandler#1#2%
+% {\expandafter\let\csname#2namespace\endcsname#1%
+ {\letcsname#2namespace\endcsname#1%
\normalexpanded
{\mult_interfaces_install_parameter_hash_handler
{\noexpand#1}% \??aa
@@ -365,23 +337,16 @@
% todo: inline the def/let
-% \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
-% {\ifx#2\relax\let#2\empty\fi
-% \protected\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate)
-% \protected\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate)
-% \protected\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2
-% \protected\def#6{\mult_interfaces_lete{#1#2:}}}% ##1
-%
% \startinterface english
\protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
{\ifx#2\relax\let#2\empty\fi
- \protected\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
- \protected\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
- \protected\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2
- \protected\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1
+ \frozen\protected\def#3##1{\defcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \frozen\protected\def#4##1{\edefcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \frozen\protected\def#5##1{\letcsname#1#2:##1\endcsname}% ##1 ##2
+ \frozen\protected\def#6##1{\letcsname#1#2:##1\endcsname\empty}}% ##1
% \stopinterface
-\protected\def\installparametersethandler#1#2%
+\permanent\protected\def\installparametersethandler#1#2%
{\normalexpanded
{\mult_interfaces_install_parameter_set_handler
{\noexpand#1}% \??aa
@@ -398,23 +363,19 @@
\let\currentcolorparameter\empty
\protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
- {\protected\def#2##1##2% style color
+ {\frozen\protected\def#2##1##2% style color
{\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
- %\ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
\ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi
\edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
- %\ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
\ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}%
- \protected\def#3##1% style
+ \frozen\protected\def#3##1% style
{\edef\currentstyleparameter{#1{##1}}% this name is public
- %\ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
\ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}%
- \protected\def#4##1% color
+ \frozen\protected\def#4##1% color
{\edef\currentcolorparameter{#1{##1}}% this name is public
- %\ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}%
\ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}}
-\protected\def\installstyleandcolorhandler#1#2%
+\permanent\protected\def\installstyleandcolorhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_style_and_color_handler
\expandafter\noexpand\csname #2parameter\endcsname
@@ -424,123 +385,107 @@
\let\definehandlerparent\empty
-% \def\mult_check_for_parent#1#2#3#4%
-% {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else
-% \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
-% \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
-% \fi \fi}
-
\def\mult_check_for_parent#1#2#3#4%
{\ifcsname#1#4:\s!parent\endcsname\orelse\ifx#4\empty\else
\writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
+% \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
+ \edefcsname#1#4:\s!parent\endcsname{#2}%
\fi}
-%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
-%def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
-%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
-
\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi}
\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname}
\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname}
-\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
- {\ifx#4\relax\let#4\empty\fi % see \defineregister
- \protected\def#2{\dotripleempty#5}%
+\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8% why is \expanded still needed in clones
+ {\ifx#4\relax\let#4\empty\fi % see \defineregister
+ \newtoks#5%
\newtoks#6%
- \newtoks#7%
- \protected\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
- {\let#9#4%
- \edef#4{##1}%
- \ifthirdargument
- \the#6% predefine
- \edef#8{##2}%
- \mult_check_for_parent{#1}{#3}#4#8%
- \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
- \mult_interfaces_get_parameters{#1#4:}[##3]%
- \orelse\ifsecondargument
- \the#6% predefine
+ \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
+ {\let#8#4%
+ % watch out: no \edef#4{##1} before the ifarguments because #1 can have macros
+ \ifarguments
+ \let#4\empty
+ \the#5% predefine
+ \let#7\empty
+ \letcsname#1#4:\s!chain\endcsname\empty
+ \edefcsname#1#4:\s!parent\endcsname{#3}%
+ \or
+ \edef#4{##1}%
+ \the#5% predefine
+ \let#7\empty
+ \edefcsname#1#4:\s!chain\endcsname{##1}%
+ \edefcsname#1#4:\s!parent\endcsname{#3}%
+ \or
+ \edef#4{##1}%
+ \the#5% predefine
\relax
- %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=^^^^0003^^^^0003^^^^0004%
-% \ifcondition\mult_aux_no_assignment_indeed##2\ignorearguments
-% \edef#8{##2}%
-% \mult_check_for_parent{#1}{#3}#4#8%
-% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
-% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
-% \else
-% \let#8\empty
-% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
-% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
-% \mult_interfaces_get_parameters{#1#4:}[##2]%
-% \fi
\ifhastok={##2}%
- \let#8\empty
- \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \let#7\empty
+ \edefcsname#1#4:\s!chain\endcsname{##1}%
+ \edefcsname#1#4:\s!parent\endcsname{#3}%
\mult_interfaces_get_parameters{#1#4:}[##2]%
\else
- \edef#8{##2}%
- \ifempty#8%
- \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \edef#7{##2}%
+ \ifempty#7%
+ \edefcsname#1#4:\s!chain\endcsname{##1}%
+ \edefcsname#1#4:\s!parent\endcsname{#3}%
\else
- \mult_check_for_parent{#1}{#3}#4#8%
- \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+ \mult_check_for_parent{#1}{#3}#4#7%
+ \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+ \edefcsname#1#4:\s!parent\endcsname{#1##2}%
\fi
\fi
- \else
- \the#6% predefine
- \let#8\empty
- \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
- \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \or
+ \edef#4{##1}%
+ \the#5% predefine
+ \edef#7{##2}%
+ \mult_check_for_parent{#1}{#3}#4#7%
+ \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+ \edefcsname#1#4:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#4:}[##3]%
\fi
- \the#7%
- \let#4#9}}
+ \the#6%
+ \let#4#8}}
-\protected\def\installdefinehandler#1#2#3%
+\permanent\protected\def\installdefinehandler#1#2#3%
{\normalexpanded
{\mult_interfaces_install_define_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname define#2\endcsname
{\noexpand#3}% root
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname define_#2\endcsname % semi-public
\expandafter\noexpand\csname everypreset#2\endcsname
\expandafter\noexpand\csname everydefine#2\endcsname
\expandafter\noexpand\csname current#2parent\endcsname
\expandafter\noexpand\csname saved_defined_#2\endcsname}}
-\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9%
+\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
{\ifx#3\relax\let#3\empty\fi
- \protected\def#2{\dodoubleempty#4}%
- \protected\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
- \newtoks#5%
- \newtoks#8%
- \protected\def#4[##1][##2]% maybe helper
- {\let#7#3%
- \ifsecondargument
- \def#9####1% we will have a simple one as well
+ \protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
+ \newtoks#4%
+ \newtoks#7%
+ \frozen\tolerant\protected\def#2[##1]##*[##2]% maybe helper
+ {\let#6#3%
+ \ifnum\lastarguments=\plustwo
+ \def#8####1% we will have a simple one as well
{\edef#3{####1}%
\mult_interfaces_get_parameters{#1#3:}[##2]%
- \the#5}%
- \processcommalist[##1]#9%
+ \the#4}%
+ \processcommalist[##1]#8%
\else
\let#3\empty
\mult_interfaces_get_parameters{#1:}[##1]%
- \the#5%
+ \the#4%
\fi
- \let#3#7%
- \the#8}}
+ \let#3#6%
+ \the#7}}
-\protected\def\installsetuphandler#1#2%
+\permanent\protected\def\installsetuphandler#1#2%
{\normalexpanded
{\mult_interfaces_install_setup_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname setup_#2\endcsname % semi-public
\expandafter\noexpand\csname everysetup#2\endcsname
\expandafter\noexpand\csname setupcurrent#2\endcsname
\expandafter\noexpand\csname saved_setup_current#2\endcsname
@@ -552,10 +497,9 @@
\let\doingrootsetnamed \plusthree % \setuplayout[name]
\let\doingrootsetroot \plusfour % \setuplayout
-\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
- {\ifx#3\relax\let#3\empty\fi
- \protected\def#2{\dodoubleempty#4}%
- \protected\def#5{\mult_interfaces_get_parameters{#1#3:}}}
+\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3%
+ {\ifx#2\relax\let#2\empty\fi
+ \frozen\protected\def#3{\mult_interfaces_get_parameters{#1#2:}}}
\protected\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
{\newtoks#5%
@@ -563,37 +507,15 @@
\newtoks#8%
\newtoks#9%
\ifx#6\relax\let#6\empty\fi
- \protected\def#4[##1][##2]% maybe helper
- {\ifsecondargument % no commalist here
- % \setuplayout[whatever][key=value]
- \let#7#3%
- \let#6#3%
- \edef#3{##1}%
- #2\doingrootsetupnamed
- \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \frozen\tolerant\protected\def#4[##1]##*[##2]% maybe helper
+ {\ifarguments
+ % \setuplayout
+ \let#6#3% % previous becomes current
+ \let#3\empty % current becomes empty
+ #2\doingrootsetroot
\the#5%
- \ifx#3#6\the#8\fi % only switchsetups if previous == current
- \let#3#7%
- \orelse\iffirstargument
- %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004%
-% \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments
-% % \setuplayout[whatever]
-% \let#6#3% % previous becomes current
-% \edef#3{##1}% this will catch reset so one needs to test for it
-% #2\doingrootsetnamed
-% \the#5% % we can check for previous vs current
-% \the#8% switchsetups
-% \else
-% % \setuplayout[key=value]
-% \let#7#3%
-% \let#6#3%
-% \let#3\empty
-% #2\doingrootsetuproot
-% \mult_interfaces_get_parameters{#1:}[##1]%
-% \the#5%
-% \the#8% switchsetups
-% \let#3#7%
-% \fi
+ \the#8% switchsetups
+ \or
\ifhastok={##1}%
% \setuplayout[key=value]
\let#7#3%
@@ -620,111 +542,113 @@
\the#8% switchsetups
\fi
\fi
- \else
- % \setuplayout
- \let#6#3% % previous becomes current
- \let#3\empty % current becomes empty
- #2\doingrootsetroot
+ \or
+ % \setuplayout[whatever][key=value]
+ \let#7#3%
+ \let#6#3%
+ \edef#3{##1}%
+ #2\doingrootsetupnamed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
\the#5%
- \the#8% switchsetups
+ \ifx#3#6\the#8\fi % only switchsetups if previous == current
+ \let#3#7%
\fi
#2\zerocount % mode is always zero at the end
\the#9}}
-\protected\def\installswitchsetuphandler#1#2%
+\permanent\protected\def\installswitchsetuphandler#1#2%
{\normalexpanded
{\mult_interfaces_install_switch_setup_handler_a
{\noexpand#1}% \??aa
- \expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname setup_#2\endcsname % semi-public
\expandafter\noexpand\csname setupcurrent#2\endcsname
\mult_interfaces_install_switch_setup_handler_b
{\noexpand#1}% \??aa
\expandafter\noexpand\csname #2setupmode\endcsname
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname everysetup#2\endcsname
\expandafter\noexpand\csname previous#2\endcsname
\expandafter\noexpand\csname saved_setup_current#2\endcsname
\expandafter\noexpand\csname everyswitch#2\endcsname
\expandafter\noexpand\csname everysetup#2root\endcsname}}
-\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9%
+\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
{\ifx#3\relax\let#3\empty\fi
- \protected\def#2{\dotripleempty#4}%
- \protected\def#6{\mult_interfaces_get_parameters{#1#3:}}%
- \newtoks#5%
- \def#4[##1][##2][##3]%
- {\let#8#3%
- \ifthirdargument
- \def#9####1%
- {\edef#3{####1}%
- \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
- \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
- \the#5}%
- \processcommalist[##1]#9%
- \orelse\ifsecondargument
- \def#9####1%
- {\edef#3{####1}%
- #7% checks parent and sets if needed
- \mult_interfaces_get_parameters{#1#3:}[##2]%
- \the#5}%
- \processcommalist[##1]#9%
- \else
+ \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}%
+ \newtoks#4%
+ \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]%
+ {\let#7#3%
+ \ifarguments
\let#3\empty
- \mult_interfaces_get_parameters{#1:}[##1]%
\the#5%
+ \or
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#4%
+ \or
+ \def#8####1%
+ {\edef#3{####1}%
+ #6% checks parent and sets if needed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#4}%
+ \processcommalist[##1]#8%
+ \or
+ \def#8####1%
+ {\edef#3{####1}%
+ \defcsname#1#3:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
+ \the#4}%
+ \processcommalist[##1]#8%
\fi
- \let#3#8}}
+ \let#3#7}}
-\protected\def\installautosetuphandler#1#2%
+\permanent\protected\def\installautosetuphandler#1#2%
{\normalexpanded
{\mult_interfaces_install_auto_setup_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname setup_#2\endcsname % semi-public
\expandafter\noexpand\csname everysetup#2\endcsname
\expandafter\noexpand\csname setupcurrent#2\endcsname
\expandafter\noexpand\csname check#2parent\endcsname
\expandafter\noexpand\csname saved_setup_current#2\endcsname
\expandafter\noexpand\csname nested_setup_current#2\endcsname}}
-\protected\def\installbasicparameterhandler#1#2%
+\permanent\protected\def\installbasicparameterhandler#1#2%
{\installparameterhandler {#1}{#2}%
\installparameterhashhandler{#1}{#2}%
\installparametersethandler {#1}{#2}%
\installrootparameterhandler{#1}{#2}}
-\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+\permanent\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
{\installbasicparameterhandler{#1}{#2}%
\installautosetuphandler {#1}{#2}}
-\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+\permanent\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
{\installbasicparameterhandler{#1}{#2}%
\installautosetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
-\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+\permanent\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
{\installbasicparameterhandler{#1}{#2}%
\installdefinehandler {#1}{#2}{#3}%
\installsetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
-\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+\permanent\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
{\installbasicparameterhandler{#1}{#2}%
\installdefinehandler {#1}{#2}{#3}%
\installswitchsetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
-\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups
+\permanent\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups
{\installbasicparameterhandler{#1}{#2}%
\installdefinehandler {#1}{#2}{#3}%
\installautosetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
-\protected\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
+\permanent\protected\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
{\installbasicparameterhandler{#1}{#2}%
\installsetuphandler {#1}{#2}%
\installstyleandcolorhandler {#1}{#2}}
@@ -741,13 +665,11 @@
%D We don't need colons for such simple cases.
\protected\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
-%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
- {\def#3##1{\begincsname#1##1\endcsname}%
- \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
- % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
- \def#5##1{\begincsname#1##1\endcsname}}
+ {\frozen\def#3##1{\begincsname#1##1\endcsname}%
+ \frozen\def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
+ \frozen\def#5##1{\begincsname#1##1\endcsname}}
-\protected\def\installdirectparameterhandler#1#2%
+\permanent\protected\def\installdirectparameterhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_direct_parameter_handler
{\noexpand#1}%
@@ -756,36 +678,28 @@
\expandafter\noexpand\csname detokenized#2parameter\endcsname
\expandafter\noexpand\csname direct#2parameter\endcsname}}
-\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
- {\protected\def#2{\dosingleempty#3}%
- \newtoks#5%
- \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
- \def#4{\mult_interfaces_get_parameters#1}}
+\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4%
+ {\newtoks#4%
+ \frozen\protected\def#2[##1]{\ifarguments\or\mult_interfaces_get_parameters#1[##1]\fi\the#4}%
+ \frozen\def#3{\mult_interfaces_get_parameters#1}}
-\protected\def\installdirectsetuphandler#1#2%
+\permanent\protected\def\installdirectsetuphandler#1#2%
{\normalexpanded
{\mult_interfaces_install_direct_setup_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname setup#2\endcsname
- \expandafter\noexpand\csname setup_#2\endcsname % semi-public
\expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
\expandafter\noexpand\csname everysetup#2\endcsname}}
-% \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
-% {\protected\def#2{\mult_interfaces_def #1}%
-% \protected\def#3{\mult_interfaces_edef#1}%
-% \protected\def#4{\mult_interfaces_let #1}%
-% \protected\def#5{\mult_interfaces_let #1\empty}}%
-
% \startinterface english
\protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
- {\protected\def#2##1{\expandafter \def\csname#1##1\endcsname}%
- \protected\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
- \protected\def#4##1{\expandafter \let\csname#1##1\endcsname}%
- \protected\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%
+ {\frozen\protected\def#2##1{\defcsname#1##1\endcsname}%
+ \frozen\protected\def#3##1{\edefcsname#1##1\endcsname}%
+ \frozen\protected\def#4##1{\letcsname#1##1\endcsname}%
+ \frozen\protected\def#5##1{\letcsname#1##1\endcsname\empty}}%
% \stopinterface
-\protected\def\installdirectparametersethandler#1#2%
+\permanent\protected\def\installdirectparametersethandler#1#2%
{\normalexpanded
{\mult_interfaces_install_direct_parameter_set_handler
{\noexpand#1}% \??aa
@@ -794,15 +708,15 @@
\expandafter\noexpand\csname let#2parameter\endcsname
\expandafter\noexpand\csname reset#2parameter\endcsname}}
-\let\installdirectstyleandcolorhandler\installstyleandcolorhandler
+\aliased\let\installdirectstyleandcolorhandler\installstyleandcolorhandler
-\protected\def\installdirectcommandhandler#1#2%
+\permanent\protected\def\installdirectcommandhandler#1#2%
{\installdirectparameterhandler {#1}{#2}%
\installdirectsetuphandler {#1}{#2}%
\installdirectparametersethandler {#1}{#2}%
\installdirectstyleandcolorhandler{#1}{#2}}
-\protected\def\installsetuponlycommandhandler#1#2%
+\permanent\protected\def\installsetuponlycommandhandler#1#2%
{\installdirectparameterhandler{#1}{#2}%
\installdirectsetuphandler {#1}{#2}%
}% maybe \installdirectparametersethandler {#1}{#2}%
@@ -830,67 +744,48 @@
% yes:\twoparameter{alpha}\par
% yes:\twoparameter{beta}\par
-\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
- {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
+\permanent\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
+ {\edefcsname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
-\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance}
- {\expandafter\edef\csname#1#2:\s!parent\endcsname{#3#4}}
+\permanent\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance}
+ {\edefcsname#1#2:\s!parent\endcsname{#3#4}}
%D Here is another experiment:
-\protected\def\installactionhandler#1%
- {\normalexpanded
- {\mult_interfaces_install_action_handler
- {#1}%
- \expandafter\noexpand\csname current#1\endcsname
- \expandafter\noexpand\csname setupcurrent#1\endcsname
- \expandafter\noexpand\csname #1_action\endcsname}}
-
-% \protected\def\mult_interfaces_install_action_handler#1#2#3#4%
-% {\protected\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
-% \protected\def#4[##1][##2]%
-% {\begingroup
-% \ifsecondargument
-% \edef#2{##1}%
-% #3[##2]%
-% \orelse\iffirstargument
-% \doifelseassignment{##1}
-% {\let#2\empty
-% #3[##1]}%
-% {\edef#2{##1}}%
-% \else
-% \let#2\empty
-% \fi
-% \directsetup{handler:action:#1}%
-% \endgroup}}
-
-\protected\def\mult_interfaces_install_action_handler#1#2#3#4%
- {\protected\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
- \protected\def#4[##1][##2]%
+\protected\def\mult_interfaces_install_action_handler#1#2#3%
+% {\frozen\tolerant\protected\expandafter\def\csname#1\endcsname[##1]##*[##2]%
+ {\frozen\tolerant\protected\defcsname#1\endcsname[##1]##*[##2]%
{\begingroup
- \ifsecondargument
- \edef#2{##1}%
- #3[##2]%
- \orelse\iffirstargument
+ \ifarguments
+ \let#2\empty
+ \or
%\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004%
-% \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments
-% \edef#2{##1}%
-% \else
-% \let#2\empty
-% #3[##1]%
-% \fi
+ % \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments
+ % \edef#2{##1}%
+ % \else
+ % \let#2\empty
+ % #3[##1]%
+ % \fi
\ifhastok={##1}%
\let#2\empty
#3[##1]%
\else
\edef#2{##1}%
\fi
- \else
- \let#2\empty
+ \or
+ \edef#2{##1}%
+ #3[##2]%
\fi
\directsetup{handler:action:#1}%
\endgroup}}
+\permanent\protected\def\installactionhandler#1%
+ {\normalexpanded
+ {\mult_interfaces_install_action_handler
+ {#1}%
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname}}
+
% First we had, in tune with the regular system variables:
%
% \starttyping
@@ -918,30 +813,23 @@
\newcount\c_mult_interfaces_n_of_namespaces
-%def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>}
-%def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>}
-
-%def\v_interfaces_prefix_template % consistently %03i>
-% {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\orelse\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi
-% \number\c_mult_interfaces_n_of_namespaces>}
-
\def\v_interfaces_prefix_template
{\number\c_mult_interfaces_n_of_namespaces>}
-\protected\def\installnamespace#1% for modules and users
+\permanent\protected\def\installnamespace#1% for modules and users
{\ifcsname ????#1\endcsname
\writestatus\m!system{duplicate user namespace '#1'}\wait
\else
\global\advance\c_mult_interfaces_n_of_namespaces\plusone
- \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
+ \immutable\edefcsname ????#1\endcsname{\v_interfaces_prefix_template}%
\fi}
-\protected\def\installcorenamespace#1%
+\permanent\protected\def\installcorenamespace#1%
{\ifcsname ??#1\endcsname
\writestatus\m!system{duplicate core namespace '#1'}\wait
\else
\global\advance\c_mult_interfaces_n_of_namespaces\plusone
- \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
+ \immutable\edefcsname ??#1\endcsname{\v_interfaces_prefix_template}%
\clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
\fi}
@@ -961,20 +849,19 @@
\letvalue\??dummy\empty
- \def\dummyparameter #1{\begincsname\??dummy#1\endcsname}
- \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname}
-\protected\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname}
-\protected\def\setexpandeddummyparameter#1{\expandafter\edef\csname\??dummy#1\endcsname}
-\protected\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname}
+\permanent \def\dummyparameter #1{\begincsname\??dummy#1\endcsname}
+\permanent \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname}
+\permanent\protected\def\setdummyparameter #1{\defcsname\??dummy#1\endcsname}
+\permanent\protected\def\setexpandeddummyparameter#1{\edefcsname\??dummy#1\endcsname}
+\permanent\protected\def\letdummyparameter #1{\letcsname\??dummy#1\endcsname}
-% \protected\def\getdummyparameters
-% {\mult_interfaces_get_parameters\??dummy}
+\edef\mult_interfaces_dummy{\??dummy} % nor immutable
-\protected\def\getdummyparameters[#1%
+\permanent\protected\def\getdummyparameters[#1%
{\if\noexpand#1]%
\expandafter\gobbleoneargument
\else
- \let\m_mult_interfaces_namespace\??dummy
+ \let\m_mult_interfaces_namespace\mult_interfaces_dummy
\expandafter\mult_interfaces_get_parameters_indeed
\fi#1}
@@ -1025,13 +912,10 @@
%
% This is a user (module) command:
-\protected\def\definenamespace
- {\dodoubleargument\mult_interfaces_define_name_space}
-
-\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
+\permanent\tolerant\protected\def\definenamespace[#1]#*[#2]% namespace settings
{\clf_definenamespace{#1}{#2}}
-\def\listnamespaces
+\permanent\protected\def\listnamespaces
{\clf_listnamespaces}
%D Helper:
@@ -1040,61 +924,52 @@
%D \showparentchain{@@am}{left}
%D \stoptyping
-\protected\def\showparentchain#1#2%
+\permanent\protected\def\showparentchain#1#2%
{\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
-% \def\mult_interfaces_show_parent_chain#1%
-% {#1 => %
-% \ifcsname#1:\s!parent\endcsname
-% \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
-% \fi}
-
\def\mult_interfaces_show_parent_chain#1%
{#1 => %
\ifcsname#1:\s!parent\endcsname
- %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
\expandafter\mult_interfaces_show_parent_chain\lastnamedcs
\fi}
%D Another helper (needs to be applied):
-\protected\def\doifelsecommandhandler#1#2% namespace name
+\permanent\protected\def\doifelsecommandhandler#1#2% namespace name
{\ifcsname#1#2:\s!parent\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\let\doifcommandhandlerelse\doifelsecommandhandler
+\aliased\let\doifcommandhandlerelse\doifelsecommandhandler
-\protected\def\doifcommandhandler#1#2% namespace name
+\permanent\protected\def\doifcommandhandler#1#2% namespace name
{\ifcsname#1#2:\s!parent\endcsname
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\protected\def\doifnotcommandhandler#1#2% namespace name
+\permanent\protected\def\doifnotcommandhandler#1#2% namespace name
{\ifcsname#1#2:\s!parent\endcsname
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\let\doifcommandhandlerelse\doifelsecommandhandler
-
% another set of (fast) helpers (grep for usage):
-\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
+\permanent\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
{\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}
\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy
{#1\endcsname#1\else#2\fi\endcsname}
-\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
+\permanent\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
{\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
-\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
+\permanent\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
{\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}
\def\syst_helpers_expand_checked_value#1#2%
@@ -1120,11 +995,6 @@
% many assignments and mechanism that do are also slow; the advantage is mostly nicer
% in tracing
-\def\s!simple{simple}
-\def\s!single{single}
-\def\s!double{double}
-\def\s!triple{triple}
-
\let\c_mult_set\relax
\protected\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7%
@@ -1134,23 +1004,23 @@
{\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname
\ifx\c_mult_set\relax
\expandafter\newtoks\c_mult_set
- \expandafter\let\csname #1_t_#6\endcsname\c_mult_set
+ \letcsname#1_t_#6\endcsname\c_mult_set
\fi}
- \protected\def#4##1%
+ \frozen\protected\def#4##1%
{\pushmacro#6%
\advance#3\plusone
\edef#6{##1}%
\unprotect}%
- \protected\def#5%
+ \frozen\protected\def#5%
{\protect
\advance#3\minusone
\popmacro#6}%
- \protected\def#7##1%
+ \frozen\protected\def#7##1%
{\edef#6{##1}%
#2%
\the\c_mult_set\relax}}
-\protected\def\installdefinitionset#1#2%
+\permanent\protected\def\installdefinitionset#1#2%
{\normalexpanded
{\mult_interfaces_install_definition_set
{\noexpand#1}% \??aa
@@ -1163,20 +1033,16 @@
\protected\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc
{\let#5#2%
- \protected\def#2%
+ \frozen\protected\def#2%
{\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}%
- \protected\def#6%
- {\dodoubleempty#7}%
- \protected\def#7[##1][##2]%
- {\ifsecondargument
- %#3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
- #3\toksapp\c_mult_set{#9[##1][##2]}%
- \orelse\iffirstargument
- %#3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
- #3\toksapp\c_mult_set{#8[##1]}%
+ \tolerant\protected\def#6[##1]##*[##2]%
+ {\ifarguments\or
+ #3\toksapp\c_mult_set{#7[##1]}%
+ \or
+ #3\toksapp\c_mult_set{#8[##1][##2]}%
\fi}}
-\protected\def\installdefinitionsetmember#1#2#3#4%
+\permanent\protected\def\installdefinitionsetmember#1#2#3#4%
{\normalexpanded
{\mult_interfaces_install_definition_set_member
{\noexpand#3}% \??aa
@@ -1185,58 +1051,33 @@
\expandafter\noexpand\csname #2_nesting_depth\endcsname
\expandafter\noexpand\csname normal_setup_#4\endcsname
\expandafter\noexpand\csname delayed_setup_#4\endcsname
- \expandafter\noexpand\csname do_delayed_setup_#4\endcsname
\expandafter\noexpand\csname setup#4_\s!single\endcsname
\expandafter\noexpand\csname setup#4_\s!double\endcsname}}
%D Another experiment:
\protected\def\mult_interfaces_install_parent_injector#1#2#3#4%
- {\protected\def#4##1%
- %{\ifx#3\empty
+ {\frozen\protected\def#4##1%
{\ifempty#3%
- \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}%
+ \defcsname#1#2:\s!parent\endcsname{#1##1}%
\fi}}
-\protected\def\installparentinjector#1#2%
+\permanent\protected\def\installparentinjector#1#2%
{\normalexpanded{\mult_interfaces_install_parent_injector
{\noexpand#1}%
\expandafter\noexpand\csname current#2\endcsname
\expandafter\noexpand\csname current#2parent\endcsname
\expandafter\noexpand\csname inject#2parent\endcsname}}
-% Faster but not used that much to make a dent in performance. But, because it's
-% cleaner anyway and also gives less tracing, we apply it a few times.
-
-% \protected\def\syst_helpers_install_macro_stack#1#2#3%
-% {\xdef\m_syst_helpers_push_macro{\csstring#1}%
-% \ifcsname#3\m_syst_helpers_push_macro\endcsname\else
-% \expandafter\newcount\csname#3\m_syst_helpers_push_macro\endcsname
-% \expandafter\edef\csname push_macro_\m_syst_helpers_push_macro\endcsname
-% {\noexpand\expandafter\glet
-% \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname
-% \noexpand#1%
-% \global\advance\csname#3\m_syst_helpers_push_macro\endcsname\plusone}%
-% \expandafter\edef\csname pop_macro_\m_syst_helpers_push_macro\endcsname
-% {\global\advance\csname#3\m_syst_helpers_push_macro\endcsname\minusone
-% \noexpand\expandafter#2%
-% \noexpand\expandafter\noexpand#1%
-% \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname}%
-% \fi}
-%
-% \protected\def\installmacrostack #1{\syst_helpers_install_macro_stack#1\let \??localpushedmacro }
-% \protected\def\installglobalmacrostack#1{\syst_helpers_install_macro_stack#1\glet\??globalpushedmacro}
-
% The \LUA\ based variant is twice as fast as the above but as said, we don't use
% this one that often. It's more about less tracing than speed here.
-\protected\def\installmacrostack#1%
+\permanent\protected\def\installmacrostack#1%
{\ifdefined#1\else\let#1\empty\fi
\protected\expandafter\gdef\csname push_macro_\csstring#1\endcsname{\localpushmacro#1}%
\protected\expandafter\gdef\csname pop_macro_\csstring#1\endcsname{\localpopmacro #1}}
-
-\protected\def\installglobalmacrostack#1%
+\permanent\protected\def\installglobalmacrostack#1%
{\ifdefined#1\else\glet#1\empty\fi
\protected\expandafter\gdef\csname push_macro_\csstring#1\endcsname{\globalpushmacro#1}%
\protected\expandafter\gdef\csname pop_macro_\csstring#1\endcsname{\globalpopmacro #1}}
@@ -1307,30 +1148,26 @@
\installcorenamespace{commalistprocessornext}
\installcorenamespace{commalistprocessoraction}
-\protected\def\installcommalistprocessor#1#2% 5 macro names overhead
- {\protected\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
- % {\noexpand\futureexpandis]%
- % \noexpand\gobbleoneargument
- % \csname\??commalistprocessorpickup#1\endcsname}
- %\protected\expandafter\edef\csname\??commalistprocessorpickup#1\endcsname
+\permanent\protected\def\installcommalistprocessor#1#2% 5 macro names overhead
+ {\protected\edefcsname\??commalistprocessor#1\endcsname[%
{\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {}
- \protected\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
+ \protected\edefcsname\??commalistprocessorwrap#1\endcsname##1]%
{\csname\??commalistprocessorfirst#1\endcsname##1,]}
- \protected\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname\relax
+ \protected\edefcsname\??commalistprocessorfirst#1\endcsname\relax
{\csname\??commalistprocessornext#1\endcsname}%
- \protected\expandafter\edef\csname\??commalistprocessornext#1\endcsname
+ \protected\edefcsname\??commalistprocessornext#1\endcsname
{\noexpand\futureexpandis]%
\noexpand\gobbleoneargument
\csname\??commalistprocessoraction#1\endcsname}
- \protected\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
+ \protected\edefcsname\??commalistprocessoraction#1\endcsname##1,%
{\noexpand#2{##1}%
\csname\??commalistprocessornext#1\endcsname}}
-\protected\def\installcommalistprocessorcommand#1#2% \processor \action
+\permanent\protected\def\installcommalistprocessorcommand#1#2% \processor \action
{\edef\p_name{\csstring#2}%
\installcommalistprocessor\p_name{#2}%
\expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname}
-\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname}
+\permanent\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname}
\protect \endinput
diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua
index ab26b7192..08baaf437 100644
--- a/tex/context/base/mkiv/mult-def.lua
+++ b/tex/context/base/mkiv/mult-def.lua
@@ -3770,7 +3770,7 @@ return {
["en"]="resetsystemmode",
["fr"]="razmodesysteme",
},
- ["resettext"]={
+ ["resettextcontent"]={
["cs"]="resettextcontent",
["de"]="resettextcontent",
["en"]="resettextcontent",
@@ -16239,6 +16239,9 @@ return {
["pe"]="پیشگفتار",
["ro"]="intro",
},
+ ["invertedshort"]={
+ ["en"]="invertedshort",
+ },
["italic"]={
["cs"]="kurziva",
["de"]="italic",
@@ -17168,6 +17171,9 @@ return {
["pe"]="نرمال",
["ro"]="normal",
},
+ ["normalshort"]={
+ ["en"]="normalshort",
+ },
["nospacing"]={
["cs"]="nospacing",
["de"]="nospacing",
@@ -17789,6 +17795,11 @@ return {
["pe"]="مراجعه",
["ro"]="referinta",
},
+ ["region"]={
+ ["en"]="region",
+ ["fr"]="region",
+ ["nl"]="gebied",
+ },
["register"]={
["cs"]="rejstrik",
["de"]="register",
diff --git a/tex/context/base/mkiv/mult-def.mkiv b/tex/context/base/mkiv/mult-def.mkiv
index 78fcdf667..0a450e8b0 100644
--- a/tex/context/base/mkiv/mult-def.mkiv
+++ b/tex/context/base/mkiv/mult-def.mkiv
@@ -37,9 +37,9 @@
% some left-overs
-\def\c!HL{HL}
-\def\c!VL{VL}
-\def\c!NL{NL}
+\defineinterfaceconstant {HL} {HL}
+\defineinterfaceconstant {VL} {VL}
+\defineinterfaceconstant {NL} {NL}
% stop todo
diff --git a/tex/context/base/mkiv/mult-fmt.lua b/tex/context/base/mkiv/mult-fmt.lua
index a91999afd..8d116c44f 100644
--- a/tex/context/base/mkiv/mult-fmt.lua
+++ b/tex/context/base/mkiv/mult-fmt.lua
@@ -38,6 +38,8 @@ local function limit(str,n)
return str
end
+-- todo: use setmacro
+
function interfaces.setuserinterface(interface,response)
local variables = interfaces.variables
local constants = interfaces.constants
diff --git a/tex/context/base/mkiv/mult-ini.lua b/tex/context/base/mkiv/mult-ini.lua
index ef04fb622..9664342ab 100644
--- a/tex/context/base/mkiv/mult-ini.lua
+++ b/tex/context/base/mkiv/mult-ini.lua
@@ -233,92 +233,6 @@ end
logs.setmessenger(context.verbatim.ctxreport)
--- function interfaces.setuserinterface(interface,response)
--- sharedstorage.currentinterface, currentinterface = interface, interface
--- sharedstorage.currentresponse, currentresponse = response, response
--- if environment.initex then
--- local nofconstants = 0
--- local nofvariables = 0
--- local nofelements = 0
--- local nofcommands = 0
--- local nofformats = 0
--- local noftranslations = 0
--- local nofsetupstrings = 0
--- --
--- local t, f, s = { }, formatters["\\ui_c{%s}{%s}"], formatters["\\ui_s{%s}"]
--- for given, constant in next, complete.constants do
--- constant = constant[interface] or constant.en or given
--- constants[constant] = given -- breedte -> width
--- nofconstants = nofconstants + 1
--- if given == constant then
--- t[nofconstants] = s(given)
--- else
--- t[nofconstants] = f(given,constant)
--- end
--- end
--- contextsprint(prtcatcodes,concat(t))
--- --
--- local t, f = { }, formatters["\\ui_v{%s}{%s}"]
--- for given, variable in next, complete.variables do
--- variable = variable[interface] or variable.en or given
--- variables[given] = variable -- ja -> yes
--- nofvariables = nofvariables + 1
--- t[nofvariables] = f(given,variable)
--- end
--- contextsprint(prtcatcodes,concat(t))
--- --
--- local t, f = { }, formatters["\\ui_e{%s}{%s}"]
--- for given, element in next, complete.elements do
--- element = element[interface] or element.en or given
--- elements[element] = given
--- nofelements = nofelements + 1
--- t[nofelements] = f(given,element)
--- end
--- contextsprint(prtcatcodes,concat(t))
--- --
--- -- local t, n, f = { }, 0, formatters["\\ui_m{%s}{%s}"]
--- local t, n, f = { }, 0, formatters["\\ui_a\\%s\\%s"]
--- for given, command in next, complete.commands do
--- command = command[interface] or command.en or given
--- if command ~= given then
--- n = n + 1
--- t[n] = f(given,command)
--- end
--- nofcommands = nofcommands + 1
--- end
--- contextsprint(prtcatcodes,"\\toksapp\\everydump{"..concat(t).."}")
--- --
--- for given, format in next, complete.messages.formats do
--- formats[given] = format[interface] or format.en or given
--- nofformats = nofformats + 1
--- end
--- --
--- for given, translation in next, complete.messages.translations do
--- translations[given] = translation[interface] or translation.en or given
--- noftranslations = noftranslations + 1
--- end
--- --
--- for given, setupstring in next, complete.setupstrings do
--- setupstring = setupstring[interface] or setupstring.en or given
--- setupstrings[given] = setupstring
--- nofsetupstrings = nofsetupstrings + 1
--- end
--- --
--- report_interface("definitions: %a constants, %a variables, %a elements, %a commands, %a formats, %a translations, %a setupstrings",
--- nofconstants,nofvariables,nofelements,nofcommands,nofformats,noftranslations,nofsetupstrings)
--- else
--- report_interface("the language(s) can only be set when making the format")
--- end
--- interfaces.currentinterface = currentinterface
--- interfaces.currentresponse = currentresponse
--- end
-
--- interfaces.implement {
--- name = "setuserinterface",
--- actions = interfaces.setuserinterface,
--- arguments = "2 strings",
--- }
-
interfaces.cachedsetups = interfaces.cachedsetups or { }
interfaces.hashedsetups = interfaces.hashedsetups or { }
diff --git a/tex/context/base/mkiv/mult-ini.mkxl b/tex/context/base/mkiv/mult-ini.mkxl
new file mode 100644
index 000000000..19c76d0cf
--- /dev/null
+++ b/tex/context/base/mkiv/mult-ini.mkxl
@@ -0,0 +1,801 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is a stripped down version of \type {mult-ini.tex}, which we keep
+%D around as \type {mult-kep.tex} for sentimental reasons. There you will find some
+%D more historic information.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Initialization}
+
+\unprotect
+
+\registerctxluafile{mult-ini}{}
+\registerctxluafile{mult-fmt}{initexonly}
+
+%D \macros
+%D [constanten,variabelen,commands]
+%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!}
+%D
+%D In the system modules we introduced some prefixed constants, variables (both
+%D macros) and registers. Apart from a tremendous saving in terms of memory and a
+%D gain in speed we use from now on prefixes when possible for just another reason:
+%D consistency and multi||linguality. Systematically using prefixed macros enables
+%D us to implement a multi||lingual user interface. Redefining these next set of
+%D prefixes therefore can have desastrous results.
+%D
+%D \startlinecorrection
+%D \starttable[|c|c|c|]
+%D \HL
+%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR
+%D \HL
+%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR
+%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\FR
+%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR
+%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR
+%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR
+%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR
+%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D In the single||lingual version we used \type {!}, \type {!!}, \type {!!!} and
+%D \type {!!!!}. In the meantime some of these are obsolete (we had some 12
+%D originally).
+
+\immutable\def\c!prefix!{c!}
+\immutable\def\k!prefix!{k!}
+\immutable\def\e!prefix!{e!}
+\immutable\def\f!prefix!{f!} % for the moment we keep this one
+\immutable\def\m!prefix!{m!}
+\immutable\def\s!prefix!{s!}
+\immutable\def\v!prefix!{v!}
+
+%D \macros
+%D [constants,variables,commands]
+%D {@@,??}
+%D
+%D Variables generated by the system can be recognized on their prefix \type {@@}.
+%D They are composed of a command (class) specific tag, which can be recognized on
+%D \type {??}, and a system constant, which has the prefix \type {c!}. We'll se some
+%D more of this.
+
+\immutable\def\??prefix {??}
+\immutable\def\@@prefix {@@}
+
+%D Just to be complete we repeat some of the already defined system constants here.
+%D Maybe their prefix \type {\s!} now falls into place.
+
+\def\s!next {next} \def\s!default {default}
+\def\s!dummy {dummy} \def\s!unknown {unknown}
+
+\def\s!do {do} \def\s!dodo {dodo}
+
+\def\s!complex {complex} \def\s!start {start}
+\def\s!simple {simple} \def\s!stop {stop}
+
+\def\s!true {true}
+\def\s!false {false}
+
+%D The word \type {height} takes 6~token memory cells. The control sequence \type
+%D {\height} on the other hand uses only one. Knowing this, we can improve the
+%D performance of \TEX, both is terms of speed and memory usage, by using control
+%D sequences instead of the words written in full.
+%D
+%D Where in the \ASCII\ file the second lines takes nine extra characters, \TEX\
+%D saves us 13~tokens.
+%D
+%D \starttyping
+%D \hrule width 10pt height 2pt depth 1pt
+%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt
+%D \stoptyping
+%D
+%D One condition is that we have defined \type {\s!height}, \type {\s!width} and
+%D \type {\s!depth} as respectively \type {height}, \type {width} and \type {depth}.
+%D Using this scheme therefore only makes sense when a token sequence is used more
+%D than once. Savings like this should of course be implemented in english, just
+%D because \TEX\ is english.
+
+\def\s!width {width}
+\def\s!height {height}
+\def\s!depth {depth}
+\def\s!spread {spread}
+\def\s!plus {plus}
+\def\s!minus {minus}
+\def\s!to {to}
+
+\def\s!fil {fil}
+\def\s!fill {fill}
+\def\s!filll {filll}
+
+\def\s!attr {attr}
+\def\s!axis {axis}
+\def\s!both {both}
+\def\s!bottom {bottom}
+\def\s!left {left}
+\def\s!options {options}
+\def\s!orientation{orientation}
+\def\s!reverse {reverse}
+\def\s!right {right}
+\def\s!top {top}
+\def\s!xmove {xmove}
+\def\s!xoffset {xoffset}
+\def\s!ymove {ymove}
+\def\s!yoffset {yoffset}
+
+%D \macros
+
+%D {defineinterfaceconstant,
+%D defineinterfacevariable,
+%D defineinterfaceelement,
+%D definesystemvariable,
+%D definesystemconstant,
+%D definemessageconstant,
+%D definefileconstant}
+%D
+%D The first part of this module is dedicated to dealing with multi||lingual
+%D constants and variables. When \CONTEXT\ grew bigger and bigger in terms of bytes
+%D and used string space, we switched to predefined constants. At the cost of more
+%D hash table entries, the macros not only becase more compact, they became much
+%D faster too. Maybe an even bigger advantage was that mispelling could no longer
+%D lead to problems. Even a multi||lingual interface became possible.
+%D
+%D Constants |<|we'll introduce the concept of variables later on|>| are preceded by
+%D a type specific prefix, followed by a \type {!}. To force consistency, we provide
+%D a few commands for defining such constants.
+%D
+%D \starttyping
+%D \defineinterfaceconstant {name} {meaning}
+%D \defineinterfacevariable {name} {meaning}
+%D \defineinterfaceelement {name} {meaning}
+%D \stoptyping
+%D
+%D Which is the same as:
+%D
+%D \starttyping
+%D \def\c!name{meaning}
+%D \def\v!name{meaning}
+%D \def\e!name{meaning}
+%D \stoptyping
+
+%permanent\protected\def\defineinterfaceconstant #1#2{\immutable\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
+\permanent\protected\def\defineinterfacevariable #1#2{\immutable\expandafter\def\csname\v!prefix!#1\endcsname{#2}}
+\permanent\protected\def\defineinterfaceelement #1#2{\immutable\expandafter\def\csname\e!prefix!#1\endcsname{#2}}
+
+%D Next come some interface independant constants:
+%D
+%D \starttyping
+%D \definefileconstant {name} {meaning}
+%D \stoptyping
+
+\permanent\protected\def\definefileconstant #1#2{\immutable\expandafter\def\csname\f!prefix!#1\endcsname{#2}}
+
+%D And finaly we have the one argument, space saving constants
+%D
+%D \starttyping
+%D \definesystemconstant {name}
+%D \definemessageconstant {name}
+%D \stoptyping
+
+% for now we check if a system variable has been defined, till we fixed all duplicate definitions
+
+\permanent\protected\def\definesystemconstant #1{\immutable\expandafter\def\csname\s!prefix!#1\endcsname{#1}}
+\permanent\protected\def\definemessageconstant #1{\immutable\expandafter\def\csname\m!prefix!#1\endcsname{#1}}
+
+%D In a parameter driven system, some parameters are shared by more system
+%D components. In \CONTEXT\ we can distinguish parameters by a unique prefix. Such a
+%D prefix is defined with:
+%D
+%D \starttyping
+%D \definesystemvariable {name}
+%D \stoptyping
+
+\permanent\protected\def\definesystemvariable#1{\immutable\expandafter\edef\csname\??prefix#1\endcsname{\@@prefix#1}}
+
+\definesystemvariable{ms}
+
+%D \macros
+%D {selectinterface,
+%D defaultinterface, currentinterface, currentresponses}
+%D
+%D With \type {\selectinterface} we specify the language we are going to use. The
+%D system asks for the language wanted, and defaults to \type {\currentinterface}
+%D when we just give \type {enter}. By default the message system uses the current
+%D interface language, but \type {\currentresponses} can specify another language
+%D too.
+%D
+%D Because we want to generate formats directly too, we do not ask for interface
+%D specifications when these are already defined (like in cont-nl.tex and alike).
+
+\ifdefined\defaultinterface
+
+ \permanent\protected\def\selectinterface
+ {\writestatus{interface}{defining \currentinterface\space interface}%
+ %writeline
+ \writestatus{interface}{using \currentresponses\space messages}%
+ %\writeline
+ \enforced\permanent\let\selectinterface\relax}
+
+\else
+
+ \def\defaultinterface{english}
+
+ \permanent\overloaded\protected\def\selectinterface
+ {\enforced\permanent\protected\def\selectinterface##1##2%
+ {\bgroup
+ \endlinechar\minusone
+ \global\read16 to ##1
+ \egroup
+ \doifnothing\currentinterface{\let##1=##2}%
+ \doifundefined{\s!prefix!##1}{\let##1=##2}}%
+ \selectinterface\currentinterface\defaultinterface
+ \writestatus{interface}{defining \currentinterface\space interface}%
+ %\writeline
+ \selectinterface\currentresponses\currentinterface
+ \writestatus{interface}{using \currentresponses\space messages}%
+ %\writeline
+ \enforced\permanent\let\selectinterface\relax}
+
+\fi
+
+\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi
+\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi
+
+%D \macros
+%D {startinterface}
+%D
+%D Sometimes we want to define things only for specific interface languages. This
+%D can be done by means of the selector:
+%D
+%D \starttyping
+%D \startinterface language
+%D
+%D language specific definitions & commands
+%D
+%D \stopinterface
+%D \stoptyping
+
+\permanent\protected\def\startinterface #1
+ {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}}
+
+\aliased\let\stopinterface\relax
+
+%D \macros
+%D {startmessages,
+%D getmessage,
+%D showmessage,
+%D makemessage}
+%D
+%D A package as large as \CONTEXT\ can hardly function without a decent message
+%D mechanism. Due to its multi||lingual interface, the message subsystem has to be
+%D multi||lingual too. A major drawback of this feature is that we have to code
+%D messages. As a result, the source becomes less self documented. On the other
+%D hand, consistency will improve.
+%D
+%D Because the overhead in terms of entries in the (already exhausted) hash table
+%D has to be minimal, messages are packed in libraries. We can extract a message
+%D from such a library in three ways:
+%D
+%D \starttyping
+%D \getmessage {library} {tag}
+%D \showmessage {library} {tag} {data}
+%D \makemessage {library} {tag} {data}
+%D \stoptyping
+%D
+%D The first command gets the message \type {tag} from the \type {library}
+%D specified. The other commands take an extra argument: a list of items to be
+%D inserted in the message text. While \type {\showmessage} shows the message at the
+%D terminal, the other commands generate the message as text. Before we explain the
+%D \type {data} argument, we give an example of a library.
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D title: something
+%D 1: first message
+%D 2: second (--) message --
+%D \stopmessages
+%D \stoptyping
+%D
+%D The first message is a simple one and can be shown with:
+%D
+%D \starttyping
+%D \showmessage {alfa} {1} {}
+%D \stoptyping
+%D
+%D The second message on the other hand needs some extra data:
+%D
+%D \starttyping
+%D \showmessage {alfa} {2} {and last,to you}
+%D \stoptyping
+%D
+%D This message is shown as:
+%D
+%D \starttyping
+%D something : second (and last) message to you
+%D \stoptyping
+%D
+%D As we can see, the title entry is shown with the message. The data fields are
+%D comma separated and are specified in the message text by \type {--}.
+%D
+%D It is not required to define all messages in a library at once. We can add
+%D messages to a library in the following way:
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D 10: tenth message
+%D \stopmessages
+%D \stoptyping
+%D
+%D Because such definitions can take place in different modules, the system gives a
+%D warning when a tag occurs more than once. The first occurrence takes preference
+%D over later ones, so we had better use a save offset, as shown in the example. As
+%D we can see, the title field is specified only the first time!
+%D
+%D Because we want to check for duplicate tags, the macros are a bit more
+%D complicated than neccessary. The \NEWLINE\ token is used as message separator.
+%D
+%D For internal purposes one can use \type {\setmessagetext}, which puts the message
+%D text asked for in \type {\currentmessagetext}.
+%D
+%D These will become obsolete:
+
+\permanent\protected\def\startmessages #1 library: #2 %
+ {\begingroup
+ \ifcsname\m!prefix!#2\endcsname\else\immutable\setgvalue{\m!prefix!#2}{#2}\fi
+ \catcode\endoflineasciicode\othercatcode
+ \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}}
+
+\def\mult_messages_start_yes#1#2\stopmessages
+ {\clf_setinterfacemessages{#1}{#2}%
+ \endgroup}
+
+\def\mult_messages_start_nop#1#2\stopmessages
+ {\endgroup}
+
+\let\stopmessages\relax
+
+\permanent\protected\def\setinterfacemessage#1#2#3%
+ {\ifcsname\m!prefix!#1\endcsname\else\immutable\setgvalue{\m!prefix!#1}{#1}\fi
+ \clf_setinterfacemessage{#1}{#2}{#3}}
+
+\pushoverloadmode
+
+\permanent\protected\def\setmessagetext #1#2{\relax\edef\currentmessagetext{\clf_getmessage{#1}{#2}}}
+\permanent\protected\def\getmessage #1#2{\relax\clf_getmessage{#1}{#2}}
+\permanent\protected\def\doifelsemessage #1#2{\relax\clf_doifelsemessage{#1}{#2}}
+\permanent\protected\def\showmessage #1#2#3{\relax\clf_showmessage{#1}{#2}{#3}}
+\permanent\protected\def\writestatus #1#2{\relax\clf_writestatus{#1}{#2}}
+\permanent\protected\def\message {\relax\clf_message}
+
+\popoverloadmode
+
+\aliased\let\doifmessageelse\doifelsemessage
+
+\permanent\protected\def\inlinemessage #1{\dontleavehmode{\tttf#1}}
+\permanent\protected\def\displaymessage#1{\blank\inlinemessage{#1}\blank}
+
+\permanent\let\getsetupstring\clf_getsetupstring
+\permanent\let\rawsetupstring\clf_rawsetupstring
+
+%D For old times sake:
+
+\let\showwarning\showmessage
+
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue
+%D
+%D We already defined these auxiliary macros in the system modules. Starting with
+%D this module however, we have to take multi||linguality a bit more serious.
+%D
+%D In due time, when we exclusively use the parameter handler code, we can drop the
+%D backmapping (\type{\c!k...}) and make \type {\c!c...} similar to \type {\v!...}.
+%D In that case we can simply the following setters.
+
+\pushoverloadmode
+
+\permanent\protected\def\doletvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\permanent\protected\def\dosetvalue #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\permanent\protected\def\dosetevalue #1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\permanent\protected\def\dosetgvalue #1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\permanent\protected\def\dosetxvalue #1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\permanent\protected\def\doresetvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\permanent\protected\def\doignorevalue#1#2#3{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+
+\permanent\protected\def\docopyvalue#1#2#3%
+ {\ifcsname\k!prefix!#3\endcsname
+ \expandafter\def\csname#1\csname\k!prefix!#3\endcsname\expandafter\endcsname\expandafter
+ {\csname#2\csname\k!prefix!#3\endcsname\endcsname}%
+ \else
+ \expandafter\def\csname#1#3\expandafter\endcsname\expandafter
+ {\csname#2#3\endcsname}%
+ \fi}
+
+\startinterface english
+
+ \permanent\protected\def\doletvalue #1#2{\expandafter \let\csname#1#2\endcsname}
+ \permanent\protected\def\dosetvalue #1#2{\expandafter \def\csname#1#2\endcsname}
+ \permanent\protected\def\dosetevalue #1#2{\expandafter\edef\csname#1#2\endcsname}
+ \permanent\protected\def\dosetgvalue #1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \permanent\protected\def\dosetxvalue #1#2{\expandafter\xdef\csname#1#2\endcsname}
+ \permanent\protected\def\doresetvalue #1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \permanent\protected\def\doignorevalue#1#2#3{\expandafter \let\csname#1#2\endcsname\empty}
+
+ \permanent\protected\def\docopyvalue#1#2#3%
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter
+ {\csname#2#3\endcsname}}
+
+\stopinterface
+
+\popoverloadmode
+
+%D We can now redefine some messages that will be introduced in the multi||lingual
+%D system module.
+
+\permanent\protected\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}}
+\permanent\protected\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}}
+\permanent\protected\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}}
+
+%D \CONTEXT\ is a parameter driven package. This means that users instruct the
+%D system by means of variables, values and keywords. These instructions take the
+%D form:
+%D
+%D \starttyping
+%D \setupsomething[some variable=some value, another one=a keyword]
+%D \stoptyping
+%D
+%D or by keyword only:
+%D
+%D \starttyping
+%D \dosomething[this way,that way,no way]
+%D \stoptyping
+%D
+%D Because the same variables can occur in more than one setup command, we have to
+%D be able to distinguish them. This is achieved by assigning them a unique prefix.
+%D
+%D Imagine a setup command for boxed text, that enables us to specify the height and
+%D width of the box. Behide the scenes the command
+%D
+%D \starttyping
+%D \setupbox [width=12cm, height=3cm]
+%D \stoptyping
+%D
+%D results in something like
+%D
+%D \starttyping
+%D \<box><width> {12cm}
+%D \<box><height> {3cm}
+%D \stoptyping
+%D
+%D while a similar command for specifying the page dimensions
+%D of an \cap {A4} page results in:
+%D
+%D \starttyping
+%D \<page><width> {21.0cm}
+%D \<page><height> {27.9cm}
+%D \stoptyping
+%D
+%D The prefixes \type {<box>} and \type {<page>} are hidden from users and can
+%D therefore be language independant. Variables on the other hand, differ for each
+%D language:
+%D
+%D \starttyping
+%D \<box><color> {<blue>}
+%D \<box><kleur> {<blauw>}
+%D \<box><couleur> {<blue>}
+%D \stoptyping
+%D
+%D In this example we can see that the assigned values or keywords are language
+%D dependant too. This will be a complication when defining multi||lingual setup
+%D files.
+%D
+%D A third phenomena is that variables and values can have a similar meaning.
+%D
+%D \starttyping
+%D \<pagenumber><location> {<left>}
+%D \<skip><left> {12cm}
+%D \stoptyping
+%D
+%D A (minor) complication is that where in english we use \type {<left>}, in dutch
+%D we find both \type {<links>} and \type {<linker>}. This means that when we use
+%D some sort of translation table, we have to distinguish between the variables at
+%D the left side and the fixed values at the right.
+%D
+%D The same goes for commands that are composed of different user supplied and/or
+%D language specific elements. In english we can use:
+%D
+%D \starttyping
+%D \<empty><figure>
+%D \<empty><intermezzo>
+%D \stoptyping
+%D
+%D But in dutch we have the following:
+%D
+%D \starttyping
+%D \<lege><figuur>
+%D \<leeg><intermezzo>
+%D \stoptyping
+%D
+%D These subtle differences automatically lead to a solution where variables,
+%D values, elements and other components have a similar logical name (used in
+%D macro's) but a different meaning (supplied by the user).
+%D
+%D Our solution is one in which the whole system is programmed in terms of
+%D identifiers with language specific meanings. In such an implementation, each
+%D fixed variable is available as:
+%D
+%D \starttyping
+%D \<prefix><variable>
+%D \stoptyping
+%D
+%D This means that for instance:
+%D
+%D \starttyping
+%D \setupbox[width=12cm]
+%D \stoptyping
+%D
+%D expands to something like:
+%D
+%D \starttyping
+%D \def\boxwidth{12cm}
+%D \stoptyping
+%D
+%D because we don't want to recode the source, a setup command in another language
+%D has to expand to this variable, so:
+%D
+%D \starttyping
+%D \setupblock[width=12cm]
+%D \stoptyping
+%D
+%D has to result in the definition of \type {\boxwidth} too. This method enables us
+%D to build compact, fast and readable code.
+%D
+%D An alternative method, which we considered using, uses a more indirect way. In
+%D this case, both calls generate a different variable:
+%D
+%D \starttyping
+%D \def\boxwidth {12cm}
+%D \def\boxbreedte {12cm}
+%D \stoptyping
+%D
+%D And because we don't want to recode those megabytes of already developed code,
+%D this variable has to be called with something like:
+%D
+%D \starttyping
+%D \valueof\box\width
+%D \stoptyping
+%D
+%D where \type {\valueof} takes care of the translation of \type {width} or \type
+%D {breedte} to \type {width} and combining this with \type {box} to \type
+%D {\boxwidth}.
+%D
+%D One advantage of this other scheme is that, within certain limits, we can
+%D implement an interface that can be switched to another language at will, while
+%D the current approach fixes the interface at startup. There are, by the way, other
+%D reasons too for not choosing this scheme. Switching user generated commands is
+%D for instance impossible and a dual interface would therefore give a strange mix
+%D of languages.
+%D
+%D Now let's work out the first scheme. Although the left hand of the assignment is
+%D a variable from the users point of view, it is a constant in terms of the system.
+%D Both \type {width} and \type {breedte} expand to \type {width} because in the
+%D source we only encounter \type {width}. Such system constants are presented as
+%D
+%D \starttyping
+%D \c!width
+%D \stoptyping
+%D
+%D This constant is always equivalent to \type {width}. As we can see, we use \type
+%D {c!} to mark this one as constant. Its dutch counterpart is:
+%D
+%D \starttyping
+%D breedte
+%D \stoptyping
+%D
+%D When we interpret a setup command each variable is translated to it's \type{c!}
+%D counterpart. This means that \type {breedte} and \type{width} expand to \type
+%D {breedte} and \type {\c!width} which both expand to \type {width}. That way user
+%D variables become system constants.
+%D
+%D The interpretation is done by means of a general setup command \type
+%D {\getparameters} that we introduced in the system module. Let us define some
+%D simple setup command:
+%D
+%D \starttyping
+%D \protected\def\setupbox[#1]%
+%D {\getparameters[\??bx][#1]}
+%D \stoptyping
+%D
+%D This command can be used as:
+%D
+%D \starttyping
+%D \setupbox [width=3cm, height=1cm]
+%D \stoptyping
+%D
+%D Afterwards we have two variables \type {\@@bxwidth} and \type {\@@bxheight} which
+%D have the values \type {3cm} and \type {1cm} assigned. These variables are a
+%D combinatiom of the setup prefix \type {\??bx}, which expands to \type {@@bx} and
+%D the translated user supplied variables \type {width} and \type {height} or \type
+%D {breedte} and \type {hoogte}, depending on the actual language. In dutch we just
+%D say:
+%D
+%D \starttyping
+%D \stelblokin [breedte=3cm,hoogte=1cm]
+%D \stoptyping
+%D
+%D and get ourselves \type {\@@bxwidth} and \type {\@@bxheight} too. In the source
+%D of \CONTEXT, we can recognize constants and variables on their leading \type
+%D {c!}, \type {v!} etc., prefixes on \type {??} and composed variables on \type
+%D {@@}.
+%D
+%D We already saw that user supplied keywords need some special treatment too. This
+%D time we don't translate the keyword, but instead use in the source a variable
+%D which meaning depends on the interface language.
+%D
+%D \starttyping
+%D \v!left
+%D \stoptyping
+%D
+%D Which can be used in macro's like:
+%D
+%D \starttyping
+%D \processaction
+%D [\@@bxlocation]
+%D [ \v!left=>\dosomethingontheleft,
+%D \v!middle=>\dosomthinginthemiddle,
+%D \v!right=>\dosomethingontheright]
+%D \stoptyping
+%D
+%D Because variables like \type {\@@bxlocation} can have a lot of meanings,
+%D including tricky expandable tokens, we cannot translate this meaning when we
+%D compare. This means that \type {\@@bxlocation} can be \type {left} of \type
+%D {links} of whatever meaning suits the language. But because \type {\v!left} also
+%D has a meaning that suits the language, we are able to compare.
+%D
+%D Although we know it sounds confusing we want to state two important
+%D characteristics of the interface as described:
+%D
+%D \startnarrower \em
+%D user variables become system constants
+%D \stopnarrower
+%D
+%D and
+%D
+%D \startnarrower \em
+%D user constants (keywords) become system variables
+%D \stopnarrower
+%D
+%D The \type {\c!internal} is a left over from the time that the user interface
+%D documents were not using a specification alongside a keyword specification but
+%D used a shared file in which case we need to go in both directions.
+
+% temporary mkiv hack (we can best just store the whole table in memory)
+
+\permanent\overloaded\protected\def\setinterfaceconstant#1#2%
+ {\clf_setinterfaceconstant{#1}{#2}%
+ \immutable\expandafter\def\csname\c!prefix!#1\endcsname{#1}}
+
+\permanent\overloaded\protected\def\setinterfacevariable#1#2%
+ {\clf_setinterfacevariable{#1}{#2}%
+ \immutable\expandafter\def\csname\v!prefix!#1\endcsname{#2}}
+
+%D \macros
+%D {defineinterfaceconstant}
+%D
+%D Next we redefine a previously defined macro to take care of interface translation
+%D too. It's a bit redundant, because in these situations we could use the
+%D c||version, but for documentation purposes the x||alternative comes in handy.
+
+\permanent\overloaded\protected\def\defineinterfaceconstant#1#2%
+ {\immutable\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
+
+%D \macros
+%D {startelements}
+%D
+%D Due to the object oriented nature of \CONTEXT, we also need to define the
+%D elements that are used to build commands.
+%D
+%D Such elements sometimes are the same in different languages, but mostly they
+%D differ. Things can get even confusing when we look at for instance the setup
+%D commands. In english we say \type{\setup<something>}, but in dutch we have: \type
+%D {\stel<iets>in}. Such split elements are no problem, because we just define two
+%D elements. When no second part is needed, we use a \type {-}:
+
+\permanent\overloaded\protected\def\setinterfaceelement#1#2%
+ {\clf_setinterfaceelement{#1}{#2}%
+ \ifcsname\e!prefix!#1\endcsname
+ \doifnotvalue{\e!prefix!#1}{#2}{\enforced\immutable\setvalue{\e!prefix!#1}{#2}}%
+ \else
+ \enforced\immutable\setvalue{\e!prefix!#1}{#2}%
+ \fi}
+
+\permanent\protected\def\setinterfacecommand#1#2% \frozen ? \permanent ?
+ {\doifnot{#1}{#2}% todo: let when already defined
+ {\expandafter\def\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}}
+
+%D We just ignore these:
+
+\permanent\protected\def\startvariables{\gobbleuntil\stopvariables} \let\stopvariables\relax
+\permanent\protected\def\startconstants{\gobbleuntil\stopconstants} \let\stopconstants\relax
+\permanent\protected\def\startelements {\gobbleuntil\stopelements } \let\stopelements \relax
+\permanent\protected\def\startcommands {\gobbleuntil\stopcommands } \let\stopcommands \relax
+
+%D For at the \LUA\ end (experiment):
+
+\def\ui_c#1#2{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \immutable\expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english
+\def\ui_s #1{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \immutable\expandafter\gdef\csname\k!prefix!#1\endcsname{#1}} % backmapping from non english
+\def\ui_v#1#2{\immutable\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}}
+\def\ui_e#1#2{\immutable\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}}
+\def\ui_a#1#2{\frozen\protected\def#2{#1}} % will go away
+
+\startinterface english
+
+ \def\ui_c#1#2{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+ \def\ui_s #1{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+
+\stopinterface
+
+%D So much for the basic multi||lingual interface commands. The macro's can be
+%D enhanced with more testing facilities, but for the moment they suffice.
+
+\ifdefined\zwnj \else \immutable\edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+\ifdefined\zwj \else \immutable\edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+
+%D \macros
+%D {contextversion, contextversionnumber, contextversionno,
+%D contextbanner, showcontextbanner, formatversion}
+%D
+%D Out of convenience we define the banners here. This might move to the \LUA\ end.
+
+\pushoverloadmode
+
+\permanent\overloaded\def\contextbanner
+ {ConTeXt \space
+ ver: \contextversion \space \contextmark \space \space
+ fmt: \formatversion \space \space
+ int: \currentinterface/\currentresponses}
+
+\permanent\overloaded\protected\def\showcontextbanner
+ {\writestatus\m!system\empty
+ \writestatus\m!system\contextbanner
+ \writestatus\m!system\empty}
+
+\immutable\overloaded\edef\formatversion
+ {\the\normalyear.\the\normalmonth.\the\normalday}
+
+\newcount\contextversionno
+
+\ifx\contextversion\undefined
+ \immutable\edef\contextversion{\the\normalyear.\the\normalmonth.\the\normalday\space 00:00}
+\fi
+
+\permanent\overloaded\protected\def \contextversionnumber #1.#2.#3 #4:#5\relax{#1#2#3}
+ \contextversionno \expandafter\contextversionnumber\contextversion\relax
+\immutable\overloaded \edef\contextversionnumber {\the\contextversionno\space\contextmark}
+
+\popoverloadmode
+
+%D \macros
+%D {everydump}
+%D
+%D This one is only used when we generate the format.
+
+% \ifx\undefined\everydump
+% \newtoks\everydump
+% \def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump}
+% \fi
+
+% \appendtoks \showcontextbanner \to \everydump
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index 6ca7a7a40..8cf89c40a 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -12,7 +12,7 @@ return {
["constants"] = {
--
"zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive",
- "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen",
+ "plussix", "plusseven", "pluseight", "plusnine", "plusten", "pluseleven", "plustwelve", "plussixteen",
"plusfifty", "plushundred", "plusonehundred", "plustwohundred", "plusfivehundred",
"plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "maxcardminusone",
"zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxcount", "maxdimen", "scaledpoint", "thousandpoint",
@@ -67,15 +67,11 @@ return {
"doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode",
"primeasciicode", "hyphenasciicode",
--
- "frozenhsizecode", "frozenleftskipcode", "frozenrightskipcode", "frozenhangindentcode",
- "frozenhangaftercode", "frozenparindentcode", "frozenparfillskipcode", "frozenparfillleftskipcode",
- "frozenadjustspacingcode", "frozenprotrudecharscode", "frozenpretolerancecode", "frozentolerancecode",
- "frozenemergencystretchcode", "frozenloosenesscode", "frozenlastlinefitcode", "frozenlinepenaltycode",
- "frozeninterlinepenaltycode", "frozenclubpenaltycode", "frozenwidowpenaltycode",
- "frozendisplaywidowpenaltycode", "frozenbrokenpenaltycode", "frozenadjdemeritscode",
- "frozendoublehyphendemeritscode", "frozenfinalhyphendemeritscode", "frozenparshapecode",
- "frozeninterlinepenaltiescode", "frozenclubpenaltiescode", "frozenwidowpenaltiescode",
- "frozendisplaywidowpenaltiescode",
+ "frozenhsizecode", "frozenskipcode", "frozenhangcode", "frozenindentcode", "frozenparfillcode",
+ "frozenadjustcode", "frozenprotrudecode", "frozentolerancecode", "frozenstretchcode",
+ "frozenloosenesscode", "frozenlastlinecode", "frozenlinepenaltycode", "frozenclubpenaltycode",
+ "frozenwidowpenaltycode", "frozendisplaypenaltycode", "frozenbrokenpenaltycode",
+ "frozendemeritscode", "frozenshapecode", "frozenlinecode", "frozenallcode",
--
"activemathcharcode",
--
@@ -85,7 +81,7 @@ return {
--
"bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode",
"vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode",
- "discgroupcode", "insertgroupcode", "vadjustgroupcode", "vcentergroupcode", "mathabovegroupcode",
+ "discretionarygroupcode", "insertgroupcode", "vadjustgroupcode", "vcentergroupcode", "mathabovegroupcode",
"mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode",
"localboxgroupcode", "splitoffgroupcode", "splitkeepgroupcode", "preamblegroupcode",
"alignsetgroupcode", "finrowgroupcode", "discretionarygroupcode",
@@ -166,6 +162,14 @@ return {
"permitgluehyphenationmodecode", "permitallhyphenationmodecode", "permitmathreplacehyphenationmodecode",
--
"normalizelinemodecode", "indentskipmodecode", "swaphangindentmodecode", "swapparskipmodecode", "breakafterdirmodecode",
+ --
+ "noligaturingcode", "nokerningcode", "noleftligaturecode", "noleftkerncode", "norightligaturecode", "norightkerncode",
+ "noexpansioncode", "noprotrusioncode",
+ --
+ "frozenflagcode", "tolerantflagcode", "protectedflagcode", "primitiveflagcode", "permanentflagcode", "noalignedflagcode", "immutableflagcode", "mutableflagcode",
+ "globalflagcode", "overloadedflagcode", "immediateflagcode", "conditionalflagcode", "valueflagcode", "instanceflagcode",
+ --
+ "continuewhenlmtxmode"
},
["helpers"] = {
--
@@ -200,6 +204,7 @@ return {
--
"strippedcsname","checkedstrippedcsname",
--
+ "nofarguments",
"firstargumentfalse", "firstargumenttrue",
"secondargumentfalse", "secondargumenttrue",
"thirdargumentfalse", "thirdargumenttrue",
@@ -477,7 +482,7 @@ return {
"carryoverpar",
"freezeparagraphproperties", "defrostparagraphproperties",
"setparagraphfreezing", "forgetparagraphfreezing",
- "updateparagraphproperties", "updateparagraphpenalties", "updateparagraphdemerits", "updateparagraphshapes",
+ "updateparagraphproperties", "updateparagraphpenalties", "updateparagraphdemerits", "updateparagraphshapes", "updateparagraphlines",
--
"lastlinewidth",
--
@@ -526,5 +531,13 @@ return {
"ifbitwiseand", "bitwise", "bitwiseshift", "bitwiseflip",
-- old ... very low level
"textdir", "linedir", "pardir", "boxdir",
+ --
+ "prelistbox", "postlistbox", "prelistcopy", "postlistcopy", "setprelistbox", "setpostlistbox",
+ --
+ "noligaturing", "nokerning", "noexpansion", "noprotrusion",
+ --
+ "futureletnexttoken", "defbackslashbreak", "letbackslashbreak",
+ --
+ "pushoverloadmode", "popoverloadmode",
}
}
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 3f9b2e15a..1a2b9bfaa 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -54,6 +54,7 @@ return {
"splitdiscards",
"splitfirstmarks",
"topmarks",
+ "tracingalignments",
"tracingassigns",
"tracinggroups",
"tracingifs",
@@ -234,6 +235,7 @@ return {
"adjustspacingstretch",
"afterassigned",
"aftergrouped",
+ "aliased",
"alignmark",
"aligntab",
"atendofgroup",
@@ -246,7 +248,7 @@ return {
"begincsname",
"beginlocalcontrol",
"boundary",
- "boxattr",
+ "boxattribute",
"boxdirection",
"boxorientation",
"boxtotal",
@@ -261,9 +263,14 @@ return {
"crampedscriptstyle",
"crampedtextstyle",
"csstring",
+ "defaliased",
+ "defcsname",
"directlua",
+ "edefaliased",
+ "edefcsname",
"efcode",
"endlocalcontrol",
+ "enforced",
"etoksapp",
"etokspre",
"everytab",
@@ -278,6 +285,7 @@ return {
"explicithyphenpenalty",
"firstvalidlanguage",
"fontid",
+ "fontspecifiedsize",
"formatname",
"frozen",
"futuredef",
@@ -288,6 +296,7 @@ return {
"glet",
"glyphdatafield",
"glyphdimensionsmode",
+ "glyphoptions",
"glyphscriptfield",
"glyphstatefield",
"gtoksapp",
@@ -308,7 +317,7 @@ return {
"ifcstok",
"ifdimval",
"ifempty",
- "iffrozen",
+ "ifflags",
"ifhastok",
"ifhastoks",
"ifhasxtoks",
@@ -316,27 +325,29 @@ return {
"ifmathparameter",
"ifmathstyle",
"ifnumval",
- "ifprotected",
+ "ifparameter",
"iftok",
- "ifusercmd",
"ignorearguments",
"ignorepars",
"immediate",
- "immediateassigned",
- "immediateassignment",
+ "immutable",
"initcatcodetable",
"insertht",
+ "instance",
+ "integerdef",
"lastarguments",
"lastnamedcs",
"lastnodesubtype",
"leftmarginkern",
+ "letaliased",
"letcharcode",
- "letdatacode",
+ "letcsname",
"letfrozen",
"letprotected",
"linedirection",
"linepar",
"localbrokenpenalty",
+ "localcontrol",
"localcontrolled",
"localinterlinepenalty",
"localleftbox",
@@ -370,18 +381,21 @@ return {
"mathstyle",
"mathsurroundmode",
"mathsurroundskip",
+ "mutable",
+ "noaligned",
"noboundary",
"nohrule",
- "nokerns",
- "noligs",
"normalizelinemode",
"nospaces",
"novrule",
"orelse",
"orunless",
"outputbox",
+ "overloaded",
+ "overloadmode",
"parattr",
"pardirection",
+ "permanent",
"postexhyphenchar",
"posthyphenchar",
"prebinoppenalty",
@@ -400,11 +414,13 @@ return {
"setfontid",
"snapshotpar",
"supmarkmode",
+ "swapcsvalues",
"textdirection",
"thewithoutunit",
"tokenized",
"toksapp",
"tokspre",
+ "tolerant",
"tpack",
"tracingfonts",
"tracingmath",
@@ -625,6 +641,7 @@ return {
"font",
"fontdimen",
"fontname",
+ "fontspecifiedname",
"futurelet",
"gdef",
"global",
@@ -638,7 +655,6 @@ return {
"hfill",
"hfilneg",
"hfuzz",
- "hoffset",
"holdinginserts",
"hrule",
"hsize",
@@ -693,7 +709,6 @@ return {
"looseness",
"lower",
"lowercase",
- "mag",
"mark",
"mathaccent",
"mathbin",
@@ -712,6 +727,8 @@ return {
"maxdeadcycles",
"maxdepth",
"meaning",
+ "meaningfull",
+ "meaningless",
"medmuskip",
"message",
"middle",
@@ -810,11 +827,14 @@ return {
"thickmuskip",
"thinmuskip",
"time",
+ "todimension",
+ "tointeger",
"toks",
"toksdef",
"tolerance",
"topmark",
"topskip",
+ "toscaled",
"tracingcommands",
"tracinglostchars",
"tracingmacros",
@@ -846,7 +866,6 @@ return {
"vfill",
"vfilneg",
"vfuzz",
- "voffset",
"vrule",
"vsize",
"vskip",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index f04f986fe..b4c006234 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -49,13 +49,13 @@
\definesystemconstant {bokmal} \definesystemconstant {nb}
\definesystemconstant {catalan} \definesystemconstant {ca}
\definesystemconstant {chinese} \definesystemconstant {cn}
-\definesystemconstant {chinese} \definesystemconstant {cn}
\definesystemconstant {croatian} \definesystemconstant {hr}
\definesystemconstant {czech} \definesystemconstant {cs}
\definesystemconstant {danish} \definesystemconstant {da}
\definesystemconstant {dutch} \definesystemconstant {nl}
\definesystemconstant {english} \definesystemconstant {en}
\definesystemconstant {estonian} \definesystemconstant {et}
+\definesystemconstant {esperanto} % \definesystemconstant {eo}
\definesystemconstant {farsi} \definesystemconstant {fa} % just persian
\definesystemconstant {finnish} \definesystemconstant {fi}
\definesystemconstant {french} \definesystemconstant {fr}
@@ -275,6 +275,7 @@
\definesystemconstant {start}
\definesystemconstant {stop}
\definesystemconstant {unknown}
+\definesystemconstant {unexpanded}
% translating setups is asking for a mess so we keep them as-is:
@@ -408,8 +409,11 @@
\definesystemconstant {text}
\definesystemconstant {paragraph}
\definesystemconstant {margintext}
+\definesystemconstant {themaintextcolor}
\definesystemconstant {line}
+\definesystemconstant {itemgroupcolumns}
+\definesystemconstant {vfrac}
\definesystemconstant {number}
\definesystemconstant {symbol}
\definesystemconstant {format}
@@ -574,19 +578,19 @@
\defineinterfaceconstant {e} {e} % can go
\defineinterfaceconstant {f} {f} % can go
-\defineinterfaceconstant {s} {s}
+%defineinterfaceconstant {s} {s}
\defineinterfaceconstant {r} {r}
\defineinterfaceconstant {g} {g}
-\defineinterfaceconstant {b} {b}
-\defineinterfaceconstant {c} {c}
+%defineinterfaceconstant {b} {b}
+%defineinterfaceconstant {c} {c}
\defineinterfaceconstant {m} {m}
-\defineinterfaceconstant {y} {y}
+%defineinterfaceconstant {y} {y}
\defineinterfaceconstant {k} {k}
-\defineinterfaceconstant {a} {a} % alternative
-\defineinterfaceconstant {t} {t} % transparency
+%defineinterfaceconstant {a} {a} % alternative
+%defineinterfaceconstant {t} {t} % transparency
\defineinterfaceconstant {p} {p} % percentage
-\defineinterfaceconstant {h} {h}
-\defineinterfaceconstant {s} {s}
+%defineinterfaceconstant {h} {h}
+%defineinterfaceconstant {s} {s}
\defineinterfaceconstant {v} {v}
\defineinterfaceconstant {rgb} {rgb}
@@ -673,7 +677,7 @@
\selectinterface
-%D Ok, here are some more, because we've got ouselves some extensions to \CONTEXT.
+%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT.
\definemessageconstant {addresses}
\definemessageconstant {documents}
diff --git a/tex/context/base/mkiv/mult-sys.mkxl b/tex/context/base/mkiv/mult-sys.mkxl
new file mode 100644
index 000000000..40fcb9c35
--- /dev/null
+++ b/tex/context/base/mkiv/mult-sys.mkxl
@@ -0,0 +1,596 @@
+%D \module
+%D [ file=mult-sys,
+%D version=1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In boring module we define a lot of obscure but useful system constants.
+%D By doing so we save lots of memory while at the same time we prevent
+%D ourself making typing errors.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / System}
+
+\unprotect
+
+%D This file is mostly the same as the \MKII\ variant but we keep extending
+%D \MKIV, so it was bout time to have a dedicated variant.
+%D
+%D The constants are grouped in such a way that there is a minimal change of
+%D conflicts.
+%D
+%D \starttyping
+%D \definesystemconstants {word}
+%D \definemessageconstant {word}
+%D \stoptyping
+%D
+%D This commands generate \type{\s!word} and \type{\m!word}.
+
+\definesystemconstant {hans}
+\definesystemconstant {taco}
+\definesystemconstant {wolfgang}
+
+%D First we define some system constants used for both the multi||lingual
+%D interface and multi||linguag typesetting.
+
+% definesystemconstant {slovene}
+% definesystemconstant {cz}
+% definesystemconstant {vn}
+
+\definesystemconstant {afrikaans} \definesystemconstant {af}
+\definesystemconstant {ancientgreek} \definesystemconstant {agr}
+\definesystemconstant {ancientlatin} \definesystemconstant {ala}
+\definesystemconstant {arabic} \definesystemconstant {ar}
+\definesystemconstant {bokmal} \definesystemconstant {nb}
+\definesystemconstant {catalan} \definesystemconstant {ca}
+\definesystemconstant {chinese} \definesystemconstant {cn}
+\definesystemconstant {croatian} \definesystemconstant {hr}
+\definesystemconstant {czech} \definesystemconstant {cs}
+\definesystemconstant {danish} \definesystemconstant {da}
+\definesystemconstant {dutch} \definesystemconstant {nl}
+\definesystemconstant {english} \definesystemconstant {en}
+\definesystemconstant {estonian} \definesystemconstant {et}
+\definesystemconstant {esperanto} % \definesystemconstant {eo}
+\definesystemconstant {farsi} \definesystemconstant {fa} % just persian
+\definesystemconstant {finnish} \definesystemconstant {fi}
+\definesystemconstant {french} \definesystemconstant {fr}
+\definesystemconstant {gbenglish} \definesystemconstant {gb}
+\definesystemconstant {german} \definesystemconstant {de}
+\definesystemconstant {greek} \definesystemconstant {gr}
+\definesystemconstant {hebrew} \definesystemconstant {he}
+\definesystemconstant {yiddish} \definesystemconstant {yi}
+\definesystemconstant {hungarian} \definesystemconstant {hu}
+\definesystemconstant {italian} \definesystemconstant {it}
+\definesystemconstant {japanese} \definesystemconstant {ja}
+\definesystemconstant {korean} \definesystemconstant {kr}
+\definesystemconstant {latin} \definesystemconstant {la}
+\definesystemconstant {lithuanian} \definesystemconstant {lt}
+\definesystemconstant {malayalam} \definesystemconstant {ml}
+\definesystemconstant {norwegian} \definesystemconstant {no}
+\definesystemconstant {nynorsk} \definesystemconstant {nn}
+\definesystemconstant {persian} \definesystemconstant {pe}
+\definesystemconstant {polish} \definesystemconstant {pl}
+\definesystemconstant {portuguese} \definesystemconstant {pt}
+\definesystemconstant {romanian} \definesystemconstant {ro}
+\definesystemconstant {russian} \definesystemconstant {ru}
+\definesystemconstant {slovak} \definesystemconstant {sk}
+\definesystemconstant {slovenian} \definesystemconstant {sl}
+\definesystemconstant {spanish} \definesystemconstant {es}
+\definesystemconstant {swedish} \definesystemconstant {sv}
+\definesystemconstant {thai} \definesystemconstant {th} % mojca mentioned it at BT2013 but we need more info
+\definesystemconstant {turkish} \definesystemconstant {tr}
+\definesystemconstant {turkmen} \definesystemconstant {tk}
+\definesystemconstant {ukenglish} \definesystemconstant {uk}
+\definesystemconstant {ukrainian} \definesystemconstant {ua}
+\definesystemconstant {usenglish} \definesystemconstant {us}
+\definesystemconstant {vietnamese} \definesystemconstant {vi}
+
+%D For proper \UNICODE\ support we need a few font related constants.
+
+\definesystemconstant {action}
+\definesystemconstant {all}
+\definesystemconstant {ampersand}
+\definesystemconstant {ascii}
+\definesystemconstant {attribute}
+\definesystemconstant {attr}
+\definesystemconstant {author}
+\definesystemconstant {auto}
+\definesystemconstant {axis}
+\definesystemconstant {a}
+\definesystemconstant {bf}
+\definesystemconstant {big}
+\definesystemconstant {binary}
+\definesystemconstant {bi}
+\definesystemconstant {blackboard}
+\definesystemconstant {black}
+\definesystemconstant {BoldItalic}
+\definesystemconstant {BoldSlanted}
+\definesystemconstant {Bold}
+\definesystemconstant {bold}
+\definesystemconstant {both}
+\definesystemconstant {bottomfloat}
+\definesystemconstant {bottom}
+\definesystemconstant {box}
+\definesystemconstant {bp}
+\definesystemconstant {bs}
+\definesystemconstant {b}
+\definesystemconstant {calligraphy}
+\definesystemconstant {Calligraphy}
+\definesystemconstant {Caps}
+\definesystemconstant {casual}
+\definesystemconstant {Casual}
+\definesystemconstant {catcodes}
+\definesystemconstant {catcodetable}
+\definesystemconstant {cc}
+\definesystemconstant {cg}
+\definesystemconstant {chain}
+\definesystemconstant {check}
+\definesystemconstant {child}
+\definesystemconstant {cite}
+\definesystemconstant {class}
+\definesystemconstant {clone}
+\definesystemconstant {cmyk}
+\definesystemconstant {cm}
+\definesystemconstant {code}
+\definesystemconstant {collapsing}
+\definesystemconstant {command}
+\definesystemconstant {compare}
+\definesystemconstant {complex}
+\definesystemconstant {counter}
+\definesystemconstant {cramped}
+\definesystemconstant {current}
+\definesystemconstant {c}
+\definesystemconstant {data}
+\definesystemconstant {dd}
+\definesystemconstant {decimal}
+\definesystemconstant {DefaultFont}
+\definesystemconstant {default}
+\definesystemconstant {depth}
+\definesystemconstant {designsize}
+\definesystemconstant {direction}
+\definesystemconstant {display}
+\definesystemconstant {document}
+\definesystemconstant {dodo}
+\definesystemconstant {done}
+\definesystemconstant {double}
+\definesystemconstant {do}
+\definesystemconstant {dtp}
+\definesystemconstant {dummy}
+\definesystemconstant {d}
+\definesystemconstant {edge}
+\definesystemconstant {effect}
+\definesystemconstant {empty}
+\definesystemconstant {em}
+\definesystemconstant {environment}
+\definesystemconstant {extensions}
+\definesystemconstant {external}
+\definesystemconstant {ex}
+\definesystemconstant {e}
+\definesystemconstant {fallbacks}
+\definesystemconstant {fallback}
+\definesystemconstant {false}
+\definesystemconstant {fax}
+\definesystemconstant {features}
+\definesystemconstant {file}
+\definesystemconstant {filll}
+\definesystemconstant {fill}
+\definesystemconstant {fil}
+\definesystemconstant {first}
+\definesystemconstant {float}
+\definesystemconstant {font}
+\definesystemconstant {forget}
+\definesystemconstant {format}
+\definesystemconstant {fraktur}
+\definesystemconstant {full}
+\definesystemconstant {f}
+\definesystemconstant {global}
+\definesystemconstant {goodies}
+\definesystemconstant {gray}
+\definesystemconstant {handler}
+\definesystemconstant {handwriting}
+\definesystemconstant {Handwriting}
+\definesystemconstant {hascaption}
+\definesystemconstant {haslevel}
+\definesystemconstant {hasnumber}
+\definesystemconstant {hasparent}
+\definesystemconstant {hassuffix}
+\definesystemconstant {hastitle}
+\definesystemconstant {head}
+\definesystemconstant {height}
+\definesystemconstant {hw}
+\definesystemconstant {hyphenmin}
+\definesystemconstant {indeed}
+\definesystemconstant {initializations}
+\definesystemconstant {insert} % maybe insertclass
+\definesystemconstant {integral}
+\definesystemconstant {internal}
+\definesystemconstant {in}
+\definesystemconstant {italics}
+\definesystemconstant {Italic}
+\definesystemconstant {italic}
+%definesystemconstant {it}
+\definesystemconstant {itemgroupcolumns}
+\definesystemconstant {kernpairs}
+\definesystemconstant {language}
+\definesystemconstant {lcgreek}
+\definesystemconstant {lefthyphenchar}
+\definesystemconstant {lefthyphenmin}
+\definesystemconstant {leftpage}
+\definesystemconstant {left}
+\definesystemconstant {level}
+\definesystemconstant {ligatures}
+\definesystemconstant {line}
+\definesystemconstant {link}
+\definesystemconstant {list}
+\definesystemconstant {local}
+\definesystemconstant {lua}
+\definesystemconstant {mapping}
+\definesystemconstant {map}
+\definesystemconstant {margintext}
+\definesystemconstant {margin}
+\definesystemconstant {marker}
+\definesystemconstant {MathBold} % not used
+\definesystemconstant {MathRomanBold}
+\definesystemconstant {MathRoman}
+\definesystemconstant {math}
+\definesystemconstant {Math} % not used
+\definesystemconstant {mblr}
+\definesystemconstant {mbrl}
+\definesystemconstant {mb}
+\definesystemconstant {middle}
+\definesystemconstant {minus}
+\definesystemconstant {mixedcolumn}
+\definesystemconstant {mi} % maybe some day a special default vector
+\definesystemconstant {mkii}
+\definesystemconstant {mkiv}
+\definesystemconstant {mm}
+\definesystemconstant {mnem} % kind of generic short tag
+\definesystemconstant {mode}
+\definesystemconstant {MonoBoldItalic}
+\definesystemconstant {MonoBoldSlanted}
+\definesystemconstant {MonoBold}
+\definesystemconstant {MonoCaps}
+\definesystemconstant {MonoItalic}
+\definesystemconstant {MonoSlanted}
+\definesystemconstant {Mono}
+\definesystemconstant {mono}
+\definesystemconstant {mrlr}
+\definesystemconstant {mrrl}
+\definesystemconstant {mr}
+\definesystemconstant {multi}
+\definesystemconstant {name}
+\definesystemconstant {next}
+\definesystemconstant {nocite}
+\definesystemconstant {nodepth}
+\definesystemconstant {noheight}
+\definesystemconstant {nomath}
+\definesystemconstant {none}
+\definesystemconstant {normal}
+\definesystemconstant {Normal}
+\definesystemconstant {nowidth}
+\definesystemconstant {numbering}
+\definesystemconstant {number}
+\definesystemconstant {options}
+\definesystemconstant {ord}
+\definesystemconstant {orientation}
+\definesystemconstant {otr}
+\definesystemconstant {pagefloat}
+\definesystemconstant {page}
+\definesystemconstant {paragraph}
+\definesystemconstant {parent}
+\definesystemconstant {patterns}
+\definesystemconstant {pc}
+\definesystemconstant {pickup}
+\definesystemconstant {plural}
+\definesystemconstant {plus}
+%definesystemconstant {pt}
+\definesystemconstant {realpage}
+\definesystemconstant {register}
+\definesystemconstant {Regular}
+\definesystemconstant {regular}
+\definesystemconstant {rel}
+\definesystemconstant {reset}
+\definesystemconstant {reverse}
+\definesystemconstant {rgb}
+\definesystemconstant {righthyphenchar}
+\definesystemconstant {righthyphenmin}
+\definesystemconstant {rightpage}
+\definesystemconstant {right}
+\definesystemconstant {rm}
+\definesystemconstant {rname}
+\definesystemconstant {rscale}
+\definesystemconstant {SansBoldItalic}
+\definesystemconstant {SansBoldSlanted}
+\definesystemconstant {SansBold}
+\definesystemconstant {SansCaps}
+\definesystemconstant {SansItalic}
+\definesystemconstant {SansSlanted}
+\definesystemconstant {Sans}
+\definesystemconstant {sans}
+\definesystemconstant {scriptscript}
+\definesystemconstant {script}
+\definesystemconstant {sc}
+\definesystemconstant {second}
+\definesystemconstant {section}
+\definesystemconstant {SerifBoldItalic}
+\definesystemconstant {SerifBoldSlanted}
+\definesystemconstant {SerifBold}
+\definesystemconstant {SerifCaps}
+\definesystemconstant {SerifItalic}
+\definesystemconstant {SerifSlanted}
+\definesystemconstant {Serif}
+\definesystemconstant {serif}
+\definesystemconstant {setups}
+\definesystemconstant {setup}
+\definesystemconstant {set}
+\definesystemconstant {themaintextcolor}
+\definesystemconstant {simple}
+\definesystemconstant {Simple}
+\definesystemconstant {single}
+\definesystemconstant {singular}
+\definesystemconstant {size}
+\definesystemconstant {slanted}
+\definesystemconstant {Slanted}
+%definesystemconstant {sl}
+\definesystemconstant {smallcaps}
+\definesystemconstant {small}
+\definesystemconstant {somewhere}
+\definesystemconstant {special}
+\definesystemconstant {spec}
+\definesystemconstant {spot}
+\definesystemconstant {spread}
+\definesystemconstant {sp}
+\definesystemconstant {ss}
+\definesystemconstant {start}
+\definesystemconstant {stop}
+\definesystemconstant {subpage}
+\definesystemconstant {subtype}
+\definesystemconstant {sub}
+\definesystemconstant {Support}
+\definesystemconstant {sygreek}
+\definesystemconstant {symbol}
+\definesystemconstant {system} % not yet interfaces messages
+\definesystemconstant {text}
+\definesystemconstant {tex}
+\definesystemconstant {tf}
+\definesystemconstant {third}
+\definesystemconstant {topfloat}
+\definesystemconstant {top}
+\definesystemconstant {to}
+\definesystemconstant {traditional}
+\definesystemconstant {triple}
+\definesystemconstant {true}
+\definesystemconstant {tt}
+\definesystemconstant {Type}
+\definesystemconstant {ucgreek}
+\definesystemconstant {uncramped}
+\definesystemconstant {unexpanded}
+\definesystemconstant {Unicode}
+\definesystemconstant {unknown}
+\definesystemconstant {userdata}
+\definesystemconstant {userpage}
+\definesystemconstant {user}
+\definesystemconstant {vfrac}
+\definesystemconstant {white}
+\definesystemconstant {width}
+\definesystemconstant {xml}
+\definesystemconstant {xmove}
+\definesystemconstant {xoffset}
+\definesystemconstant {xx}
+\definesystemconstant {x}
+\definesystemconstant {ymove}
+\definesystemconstant {yoffset}
+
+%D As the name of their define command states, the next set of constants is used in
+%D the message macro's.
+
+\definemessageconstant {backend}
+\definemessageconstant {check}
+\definemessageconstant {chemicals}
+\definemessageconstant {colors}
+\definemessageconstant {columns}
+\definemessageconstant {fields}
+\definemessageconstant {figures}
+\definemessageconstant {files}
+\definemessageconstant {floatblocks}
+\definemessageconstant {fonts}
+\definemessageconstant {handlings}
+\definemessageconstant {interactions}
+\definemessageconstant {javascripts}
+\definemessageconstant {languages}
+\definemessageconstant {layouts}
+\definemessageconstant {lua}
+\definemessageconstant {metapost}
+\definemessageconstant {publications}
+\definemessageconstant {references}
+\definemessageconstant {regimes}
+\definemessageconstant {structures}
+\definemessageconstant {symbols}
+\definemessageconstant {system}
+\definemessageconstant {textblocks}
+\definemessageconstant {verbatims}
+\definemessageconstant {versions}
+
+%D When we use numbers and dimensions the same applies as with the keywords like
+%D \type {width} and \type {plus} mentioned earlier.
+
+\immutable\def\!!ten {10}
+\immutable\def\!!twelve {12}
+\immutable\def\!!hundred {100}
+\immutable\def\!!thousand {1000}
+\immutable\def\!!tenthousand {10000}
+\immutable\def\!!maxcard {65536}
+\immutable\def\!!medcard {32768}
+
+\immutable\def\!!zeropoint {0pt}
+\immutable\def\!!onepoint {1pt}
+\immutable\def\!!twopoint {2pt}
+\immutable\def\!!threepoint {3pt}
+\immutable\def\!!fourpoint {4pt}
+\immutable\def\!!fivepoint {5pt}
+\immutable\def\!!sixpoint {6pt}
+\immutable\def\!!sevenpoint {7pt}
+\immutable\def\!!eightpoint {8pt}
+\immutable\def\!!ninepoint {9pt}
+\immutable\def\!!tenpoint {10pt}
+\immutable\def\!!elevenpoint {11pt}
+\immutable\def\!!twelvepoint {12pt}
+\immutable\def\!!fourteenpointfour {14.4pt}
+
+\immutable\def\!!plustoken {+} % todo: \??plustoken
+\immutable\def\!!minustoken {-} % todo: \??minustoken
+
+\immutable\def\__unknown__ {\string\\//} % unlikely value
+
+%D Variables are composed of a command specific tag and a user supplied variable
+%D (system constant). The tag \type {du} for instance is available as \type {\??du}
+%D and expands to \type {@@du} in composed variables.
+
+\definesystemvariable {du} % dummy, will stay
+
+% bibl:
+
+\definesystemvariable {pv} % PublicationVariable
+\definesystemvariable {pb} % PuBlication
+
+% needs checking (namespaces now)
+
+\definesystemvariable {fw} % simpleFonts by Wolfgang
+
+% old pragma
+
+\definesystemvariable {kt} % KonTakten
+\definesystemvariable {kw} % KontaktWaarde
+\definesystemvariable {st} % STickers
+\definesystemvariable {km} % KenMerk
+
+% mkii
+
+\definesystemvariable {xf} % XML File (xtag)
+\definesystemvariable {xp} % XML Processing (xtag, so still needed)
+\definesystemvariable {fo} % xml FO (xtag)
+\definesystemvariable {fx} % FoXet
+
+% mkiv
+
+%D Next we define some language independant one letter variables and keywords. We can
+%D actually make these system variables.
+
+\defineinterfaceconstant {x} {x}
+\defineinterfaceconstant {y} {y}
+\defineinterfaceconstant {w} {w}
+\defineinterfaceconstant {h} {h}
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {t} {t}
+
+\defineinterfaceconstant {a} {a} % can go
+\defineinterfaceconstant {b} {b} % can go
+\defineinterfaceconstant {c} {c} % can go
+\defineinterfaceconstant {d} {d} % can go
+\defineinterfaceconstant {e} {e} % can go
+\defineinterfaceconstant {f} {f} % can go
+
+%defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {r} {r}
+\defineinterfaceconstant {g} {g}
+%defineinterfaceconstant {b} {b}
+%defineinterfaceconstant {c} {c}
+\defineinterfaceconstant {m} {m}
+%defineinterfaceconstant {y} {y}
+\defineinterfaceconstant {k} {k}
+%defineinterfaceconstant {a} {a} % alternative
+%defineinterfaceconstant {t} {t} % transparency
+\defineinterfaceconstant {p} {p} % percentage
+%defineinterfaceconstant {h} {h}
+%defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {v} {v}
+
+\defineinterfaceconstant {rgb} {rgb}
+\defineinterfaceconstant {cmyk} {cmyk}
+\defineinterfaceconstant {mp} {mp}
+
+\defineinterfacevariable {rgb} {rgb}
+\defineinterfacevariable {cmyk} {cmyk}
+\defineinterfacevariable {mp} {mp}
+
+\defineinterfacevariable {s} {s}
+
+\defineinterfacevariable {a} {a}
+\defineinterfacevariable {b} {b}
+\defineinterfacevariable {c} {c}
+\defineinterfacevariable {d} {d}
+
+%D Special purpose variables:
+
+\immutable\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi}
+
+%D The names of files and their extensions are fixed. \CONTEXT\ uses as less
+%D files as possible. Utility files can be recognized by the first two
+%D characters of the extension: \type {tu}.
+
+%definefileconstant {utilityfilename} {texutil}
+%definefileconstant {blockextension} {tub}
+%definefileconstant {figureextension} {tuf}
+%definefileconstant {inputextension} {tui}
+%definefileconstant {outputextension} {tuo} % tup for previous run
+%definefileconstant {optionextension} {top}
+%definefileconstant {temporaryextension} {tmp}
+%definefileconstant {patternsextension} {pat}
+%definefileconstant {hyphensextension} {hyp}
+%definefileconstant {fontmapextension} {map}
+\definefileconstant {bibextension} {bbl}
+
+%D These files are loaded at start||up. They may contain system specific setups (or
+%D calls to other files), old macro's, to garantee compatibility and new macro's noy
+%D yet present in the format.
+
+\definefileconstant {sysfilename} {cont-sys.mkiv}
+\definefileconstant {newfilename} {cont-new.mkiv}
+\definefileconstant {locfilename} {cont-loc.mkiv}
+\definefileconstant {expfilename} {cont-exp.mkiv}
+\definefileconstant {fntfilename} {cont-fnt.mkiv} % not yet used
+\definefileconstant {gdsfilename} {cont-fnt.lfg} % not yet used
+
+%D The setup files for the language, font, color and special subsystems have a common
+%D prefix. This means that we have at most three characters for unique filenames.
+
+\definefileconstant {colo_run} {colo-run}
+\definefileconstant {font_run} {font-run}
+\definefileconstant {page_run} {page-run}
+\definefileconstant {symb_run} {symb-run}
+\definefileconstant {publ_tra} {publ-tra}
+
+%D For figure inclusion we need(ed):
+
+%defineinterfaceconstant {tif} {tif}
+%defineinterfaceconstant {eps} {eps}
+%defineinterfaceconstant {mps} {mps}
+%defineinterfaceconstant {jpg} {jpg}
+%defineinterfaceconstant {pdf} {pdf}
+%defineinterfaceconstant {png} {png}
+%defineinterfaceconstant {avi} {avi}
+%defineinterfaceconstant {mov} {mov}
+%defineinterfaceconstant {svg} {svg}
+\defineinterfaceconstant {tex} {tex} % Also gone?
+%defineinterfaceconstant {tmp} {tmp}
+%defineinterfaceconstant {cld} {cld}
+
+%D A careful reader will have noticed that in the module \type {mult-ini} we defined
+%D \type {\selectinterface}. We were not yet able to actually select an interface,
+%D because we still had to define the constants and variables. Now we've done so,
+%D selection is permitted.
+
+\selectinterface
+
+%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT.
+
+\definemessageconstant {addresses}
+\definemessageconstant {documents}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/node-aux.lmt b/tex/context/base/mkiv/node-aux.lmt
index ada376556..d952ec41b 100644
--- a/tex/context/base/mkiv/node-aux.lmt
+++ b/tex/context/base/mkiv/node-aux.lmt
@@ -21,7 +21,7 @@ local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local attributelist_code = nodecodes.attributelist -- temporary
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local nuts = nodes.nuts
local tonut = nuts.tonut
@@ -364,9 +364,9 @@ end
do
- local localparcodes = nodes.localparcodes
- local hmodepar_code = localparcodes.hmode_par
- local vmodepar_code = localparcodes.vmode_par
+ local parcodes = nodes.parcodes
+ local hmodepar_code = parcodes.hmode_par
+ local vmodepar_code = parcodes.vmode_par
local getnest = tex.getnest
local getsubtype = nuts.getsubtype
@@ -374,7 +374,7 @@ do
function nuts.setparproperty(action,...)
local tail = tonut(getnest().tail)
while tail do
- if getid(tail) == localpar_code then
+ if getid(tail) == par_code then
local s = getsubtype(tail)
if s == hmodepar_code or s == vmodepar_code then
return action(tail,...)
diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua
index aa7dc0292..d3c537a3b 100644
--- a/tex/context/base/mkiv/node-aux.lua
+++ b/tex/context/base/mkiv/node-aux.lua
@@ -21,7 +21,7 @@ local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local attributelist_code = nodecodes.attributelist -- temporary
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local nuts = nodes.nuts
local tonut = nuts.tonut
@@ -382,9 +382,9 @@ end
do
- local localparcodes = nodes.localparcodes
- local hmodepar_code = localparcodes.vmode_par
- local vmodepar_code = localparcodes.hmode_par
+ local parcodes = nodes.parcodes
+ local hmodepar_code = parcodes.vmode_par
+ local vmodepar_code = parcodes.hmode_par
local getnest = tex.getnest
local getsubtype = nuts.getsubtype
@@ -392,7 +392,7 @@ do
function nuts.setparproperty(action,...)
local tail = tonut(getnest().tail)
while tail do
- if getid(tail) == localpar_code then
+ if getid(tail) == par_code then
local s = getsubtype(tail)
if s == hmodepar_code or s == vmodepar_code then
return action(tail,...)
diff --git a/tex/context/base/mkiv/node-cmp.lmt b/tex/context/base/mkiv/node-cmp.lmt
index e9e7e266d..21fd700f0 100644
--- a/tex/context/base/mkiv/node-cmp.lmt
+++ b/tex/context/base/mkiv/node-cmp.lmt
@@ -192,7 +192,6 @@ end
local uses_font = direct.uses_font
local has_glyph = direct.has_glyph
local protrusion_skippable = direct.protrusion_skippable
-local prepend_prevdepth = direct.prepend_prevdepth
local make_extensible = direct.make_extensible
function node.uses_font(n,f)
@@ -207,11 +206,6 @@ function node.protrusion_skippable(n)
return protrusion_skippable(todirect(n))
end
-function node.prepend_prevdepth(n)
- local n, d = prepend_prevdepth(todirect(n))
- return tonode(n), d
-end
-
function node.make_extensible(...)
local n = make_extensible(...)
return n and tonode(n) or nil
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index ddcdcd9d0..373cce3ce 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -636,100 +636,3 @@ end
statistics.register("attribute processing time", function()
return statistics.elapsedseconds(attributes,"front- and backend")
end)
-
--- -- --
-
--- do
---
--- local cleaners = { }
--- local trace = true -- false
---
--- function attributes.cleanup()
--- if next(cleaners) then
--- local values = setmetatableindex("table")
---
--- if trace then
--- starttiming(values)
--- end
---
--- local function check(l)
--- for n, id in nextnode, l do
--- if id == hlist_code or id == vlist_code or id == glue_code then
--- local l = getlist(n)
--- if l then
--- check(l)
--- end
--- end
--- for a in next, cleaners do
--- local v = getattr(n,a)
--- if v then
--- -- values[a] = values[a] + 1
--- values[a][v] = true
--- end
--- end
--- end
--- end
---
--- local top = texgetnest("ptr")
--- for i=1,top do
--- local l = texgetnest(i)
--- if l then
--- check(tonut(l.head))
--- end
--- end
---
--- do local l
--- l = tonut(texlists.page_ins_head) if l then check(l) end
--- l = tonut(texlists.contrib_head) if l then check(l) end
--- l = tonut(texlists.page_discards_head) if l then check(l) end
--- l = tonut(texlists.split_discards_head) if l then check(l) end
--- l = tonut(texlists.page_head) if l then check(l) end
--- end
---
--- -- todo: traverseboxes
---
--- for i=0,65535 do
--- local b = getbox(i)
--- if b then
--- local l = getlist(b)
--- if l then
--- check(l)
--- end
--- end
--- end
---
--- for a, t in next, values do
--- cleaners[a](a,t)
--- end
---
--- if trace then
--- stoptiming(values)
--- local a = table.sortedkeys(values)
--- local t = statistics.elapsedtime(values)
--- local r = tex.getcount("realpageno")
--- if #a == 0 then
--- logs.report("attributes","cleaning up at page %i took %s seconds, no attributes",r,t)
--- else
--- logs.report("attributes","cleaning up at page %i took %s seconds, attributes: % t",r,t,a)
--- end
--- end
--- end
--- end
---
--- -- not yet used but when we do ... delay a call till we enable it (attr-ini.mkiv)
---
--- -- local function show(a,t) for k, v in next, t do print(a,k) end end
--- --
--- -- attributes.registercleaner(1, show)
--- -- attributes.registercleaner(2, show)
---
--- function attributes.registercleaner(a,f)
--- cleaners[a] = f
--- end
---
--- implement {
--- name = "cleanupattributes",
--- actions = attributes.cleanup,
--- }
---
--- end
diff --git a/tex/context/base/mkiv/node-fin.mkiv b/tex/context/base/mkiv/node-fin.mkiv
index 81a8fec51..2bf0e0806 100644
--- a/tex/context/base/mkiv/node-fin.mkiv
+++ b/tex/context/base/mkiv/node-fin.mkiv
@@ -19,6 +19,7 @@
\unprotect
\registerctxluafile{node-shp}{optimize}
+% \registerctxluafile{node-fin}{autosuffix,optimize} % we might generalize this one
\registerctxluafile{node-fin}{optimize} % we might generalize this one
% we might have two variants at some point (efficiency)
diff --git a/tex/context/base/mkiv/node-ini.lmt b/tex/context/base/mkiv/node-ini.lmt
index f43896d79..5cce9030d 100644
--- a/tex/context/base/mkiv/node-ini.lmt
+++ b/tex/context/base/mkiv/node-ini.lmt
@@ -43,8 +43,6 @@ local dircodes = mark(getsubtypes("dir"))
local glyphcodes = mark(getsubtypes("glyph"))
local disccodes = mark(getsubtypes("disc"))
local gluecodes = mark(getsubtypes("glue"))
-local leadercodes = mark(getsubtypes("leader"))
-local fillcodes = mark(getsubtypes("fill"))
local boundarycodes = mark(getsubtypes("boundary"))
local penaltycodes = mark(getsubtypes("penalty"))
local kerncodes = mark(getsubtypes("kern"))
@@ -54,7 +52,10 @@ local radicalcodes = mark(getsubtypes("radical"))
local accentcodes = mark(getsubtypes("accent"))
local fencecodes = mark(getsubtypes("fence"))
----- fractioncodes = mark(getsubtypes("fraction"))
-local localparcodes = mark(getsubtypes("localpar"))
+local parcodes = mark(getsubtypes("par"))
+
+local fillvalues = mark(getvalues("fill"))
+local dirvalues = mark(getvalues("dir"))
local function simplified(t)
local r = { }
@@ -65,12 +66,8 @@ local function simplified(t)
end
local nodecodes = simplified(node.types())
-local whatcodes = simplified(node.whatsits and node.whatsits() or { })
-
-local dirvalues = mark(getvalues("dir"))
-local gluevalues = mark(getvalues("glue"))
-local whatcodes = {
+local whatcodes = allocate {
literal = 0x1, [0x1] = "literal",
latelua = 0x2, [0x2] = "latelua",
userdefined = 0x3, [0x3] = "userdefined",
@@ -127,70 +124,112 @@ glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
kerncodes = allocate(swapped(kerncodes,kerncodes))
penaltycodes = allocate(swapped(penaltycodes,penaltycodes))
mathcodes = allocate(swapped(mathcodes,mathcodes))
-fillcodes = allocate(swapped(fillcodes,fillcodes))
disccodes = allocate(swapped(disccodes,disccodes))
accentcodes = allocate(swapped(accentcodes,accentcodes))
fencecodes = allocate(swapped(fencecodes,fencecodes))
-localparcodes = allocate(swapped(localparcodes,localparcodes))
+parcodes = allocate(swapped(parcodes,parcodes))
rulecodes = allocate(swapped(rulecodes,rulecodes))
-leadercodes = allocate(swapped(leadercodes,leadercodes))
usercodes = allocate(swapped(usercodes,usercodes))
noadoptions = allocate(swapped(noadoptions,noadoptions))
+
dirvalues = allocate(swapped(dirvalues,dirvalues))
-gluevalues = allocate(swapped(gluevalues,gluevalues))
literalvalues = allocate(swapped(literalvalues,literalvalues))
+fillvalues = allocate(swapped(fillvalues,fillvalues))
nodes.gluecodes = gluecodes
nodes.dircodes = dircodes
nodes.boundarycodes = boundarycodes
nodes.noadcodes = noadcodes
-nodes.nodecodes = nodecodes
nodes.whatcodes = whatcodes
nodes.listcodes = listcodes
nodes.glyphcodes = glyphcodes
nodes.kerncodes = kerncodes
nodes.penaltycodes = penaltycodes
nodes.mathcodes = mathcodes
-nodes.fillcodes = fillcodes
nodes.disccodes = disccodes
nodes.accentcodes = accentcodes
nodes.radicalcodes = radicalcodes
nodes.fencecodes = fencecodes
-nodes.localparcodes = localparcodes
+nodes.parcodes = parcodes
nodes.rulecodes = rulecodes
-nodes.leadercodes = leadercodes
nodes.usercodes = usercodes
+
nodes.noadoptions = noadoptions
+nodes.fillvalues = fillvalues
+nodes.fillcodes = fillvalues -- for now
nodes.dirvalues = dirvalues
-nodes.gluevalues = gluevalues
nodes.literalvalues = literalvalues
-nodes.subtypes = allocate {
- [nodecodes.accent] = accentcodes,
- [nodecodes.boundary] = boundarycodes,
- [nodecodes.dir] = dircodes,
- [nodecodes.disc] = disccodes,
- [nodecodes.fence] = fencecodes,
- [nodecodes.glue] = gluecodes,
- [nodecodes.glyph] = glyphcodes,
- [nodecodes.hlist] = listcodes,
- [nodecodes.kern] = kerncodes,
- [nodecodes.localpar] = localparcodes,
- [nodecodes.math] = mathcodes,
- [nodecodes.noad] = noadcodes,
- [nodecodes.penalty] = penaltycodes,
- [nodecodes.radical] = radicalcodes,
- [nodecodes.rule] = rulecodes,
- -- [nodecodes.user] = usercodes,
- [nodecodes.vlist] = listcodes,
- [nodecodes.whatsit] = whatcodes,
+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,
+ boundary = boundarycodes,
+ noad = noadcodes,
+ whatsit = whatcodes,
+ glyph = glyphcodes,
+ kern = kerncodes,
+ penalty = penaltycodes,
+ math = mathcodes,
+ disc = disccodes,
+ accent = accentcodes,
+ radical = radicalcodes,
+ fence = fencecodes,
+ par = parcodes,
+ rule = rulecodes,
+
+ vlist = listcodes,
+ hlist = listcodes,
+
+ -- list = listcodes,
+
+ -- parameter = parametercodes,
+ -- user = usercodes,
}
-table.setmetatableindex(nodes.subtypes,function(t,k)
- local v = { }
- t[k] = v
- return v
-end)
+for k, v in table.sortedhash(subtypes) do
+ local i = nodecodes[k]
+ if i and not subtypes[i] then
+ subtypes[i] = v
+ end
+end
+
+nodes.subtypes = subtypes
-- a few more friendly aliases:
@@ -198,12 +237,15 @@ nodes.skipcodes = gluecodes
nodes.directioncodes = dircodes
nodes.whatsitcodes = whatcodes
nodes.discretionarycodes = disccodes
+
nodes.directionvalues = dirvalues
-nodes.skipvalues = gluevalues
nodes.literalvalues = literalvalues
glyphcodes.glyph = glyphcodes.character
+gluecodes.parfillrightskip = gluecodes.parfillrightskip or gluecodes.parfillskip
+gluecodes.parfillskip = gluecodes.parfillskip or gluecodes.parfillrightskip
+
listcodes.row = listcodes.alignment
listcodes.column = listcodes.alignment
@@ -212,28 +254,6 @@ kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new
literalvalues.direct = literalvalues.always
-nodes.codes = allocate { -- mostly for listing
- glue = skipcodes,
- boundary = boundarycodes,
- noad = noadcodes,
- node = nodecodes,
- hlist = listcodes,
- vlist = listcodes,
- glyph = glyphcodes,
- kern = kerncodes,
- penalty = penaltycodes,
- math = mathnodes,
- fill = fillcodes,
- disc = disccodes,
- whatsit = whatcodes,
- accent = accentcodes,
- fence = fencecodes,
- rule = rulecodes,
- leader = leadercodes,
- user = usercodes,
- noadoptions = noadoptions,
-}
-
nodes.noadoptions = {
set = 0x08,
unused_1 = 0x00 + 0x08,
@@ -246,36 +266,15 @@ nodes.noadoptions = {
right = 0x14 + 0x08,
}
-local report_codes = logs.reporter("nodes","codes")
-
-function nodes.showcodes()
- local t = { }
- for name, codes in sortedhash(nodes.codes) do
- local sorted = sortedkeys(codes)
- for i=1,#sorted do
- local s = sorted[i]
- if type(s) ~= "number" then
- t[#t+1] = { name, s, codes[s] }
- end
- end
- end
- formatcolumns(t)
- for k=1,#t do
- report_codes (t[k])
- end
-end
-
-trackers.register("system.showcodes", nodes.showcodes)
-
-- We use the real node code numbers.
-local texchardef = tex.chardef
+local texsetintegervalue = tex.setintegervalue
for i=0,nodecodes.glyph do
- texchardef(nodecodes[i] .. "nodecode",i)
+ texsetintegervalue(nodecodes[i] .. "nodecode",i,"immutable")
end
for i=0,#gluecodes do
- texchardef(gluecodes[i] .. "subtypecode",i)
+ texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable")
end
-- tex.set("internalcodesmode",1) -- obsolete
diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua
index ccbd726d9..3d49d01bd 100644
--- a/tex/context/base/mkiv/node-ini.lua
+++ b/tex/context/base/mkiv/node-ini.lua
@@ -78,7 +78,6 @@ local dircodes = mark(getsubtypes("dir"))
local glyphcodes = mark(getsubtypes("glyph"))
local disccodes = mark(getsubtypes("disc"))
local gluecodes = mark(getsubtypes("glue"))
-local leadercodes = mark(getsubtypes("leader"))
local fillcodes = mark(getsubtypes("fill"))
local boundarycodes = mark(getsubtypes("boundary"))
local penaltycodes = mark(getsubtypes("penalty"))
@@ -90,7 +89,7 @@ local radicalcodes = mark(getsubtypes("radical"))
local accentcodes = mark(getsubtypes("accent"))
local fencecodes = mark(getsubtypes("fence"))
----- fractioncodes = mark(getsubtypes("fraction"))
-local localparcodes = allocate { [0] = "vmode_par", "local_box", "hmode_par", "penalty", "math" }
+local parcodes = allocate { [0] = "vmode_par", "local_box", "hmode_par", "penalty", "math" }
local function simplified(t)
local r = { }
@@ -160,15 +159,28 @@ margincodes = allocate(swapped(margincodes,margincodes))
disccodes = allocate(swapped(disccodes,disccodes))
accentcodes = allocate(swapped(accentcodes,accentcodes))
fencecodes = allocate(swapped(fencecodes,fencecodes))
-localparcodes = allocate(swapped(localparcodes,localparcodes))
+parcodes = allocate(swapped(parcodes,parcodes))
rulecodes = allocate(swapped(rulecodes,rulecodes))
-leadercodes = allocate(swapped(leadercodes,leadercodes))
usercodes = allocate(swapped(usercodes,usercodes))
noadoptions = allocate(swapped(noadoptions,noadoptions))
dirvalues = allocate(swapped(dirvalues,dirvalues))
gluevalues = allocate(swapped(gluevalues,gluevalues))
literalvalues = allocate(swapped(literalvalues,literalvalues))
+if not nodecodes.delimiter then
+ -- as in luametatex / lmtx
+ nodecodes.delimiter = nodecodes.delim
+ nodecodes[nodecodes.delimiter] = "delimiter"
+ nodecodes.delim = nil
+end
+
+if not nodecodes.par then
+ -- as in luametatex / lmtx
+ local p = nodecodes.localpar
+ nodecodes.par = p
+ nodecodes[p] = "par"
+end
+
if not gluecodes.indentskip then
gluecodes.indentskip = gluecodes.userskip
gluecodes.lefthangskip = gluecodes.userskip
@@ -179,18 +191,7 @@ if not gluecodes.indentskip then
gluecodes.parfillrightskip = gluecodes.parfillskip
end
-if CONTEXTLMTXMODE > 0 then
- whatcodes.literal = 0x1 whatcodes[0x1] = "literal"
- whatcodes.latelua = 0x2 whatcodes[0x2] = "latelua"
- whatcodes.userdefined = 0x3 whatcodes[0x3] = "userdefined"
- whatcodes.savepos = 0x4 whatcodes[0x4] = "savepos"
- whatcodes.save = 0x5 whatcodes[0x5] = "save"
- whatcodes.restore = 0x6 whatcodes[0x6] = "restore"
- whatcodes.setmatrix = 0x7 whatcodes[0x7] = "setmatrix"
- whatcodes.open = 0x8 whatcodes[0x8] = "open"
- whatcodes.close = 0x9 whatcodes[0x9] = "close"
- whatcodes.write = 0xA whatcodes[0xA] = "write"
-elseif not whatcodes.literal then
+if not whatcodes.literal then
whatcodes.literal = whatcodes.pdfliteral
whatcodes.save = whatcodes.pdfsave
whatcodes.restore = whatcodes.pdfrestore
@@ -214,9 +215,8 @@ nodes.disccodes = disccodes
nodes.accentcodes = accentcodes
nodes.radicalcodes = radicalcodes
nodes.fencecodes = fencecodes
-nodes.localparcodes = localparcodes
+nodes.parcodes = parcodes
nodes.rulecodes = rulecodes
-nodes.leadercodes = leadercodes
nodes.usercodes = usercodes
nodes.noadoptions = noadoptions
nodes.dirvalues = dirvalues
@@ -233,7 +233,7 @@ nodes.subtypes = allocate {
[nodecodes.glyph] = glyphcodes,
[nodecodes.hlist] = listcodes,
[nodecodes.kern] = kerncodes,
- [nodecodes.localpar] = localparcodes,
+ [nodecodes.par] = parcodes,
-- [nodecodes.marginkern] = margincodes,
[nodecodes.math] = mathcodes,
[nodecodes.noad] = noadcodes,
@@ -295,7 +295,6 @@ nodes.codes = allocate { -- mostly for listing
accent = accentcodes,
fence = fencecodes,
rule = rulecodes,
- leader = leadercodes,
user = usercodes,
noadoptions = noadoptions,
}
diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv
index 8a3aa65df..b52695ef6 100644
--- a/tex/context/base/mkiv/node-ini.mkiv
+++ b/tex/context/base/mkiv/node-ini.mkiv
@@ -32,16 +32,16 @@
\registerctxluafile{node-tra}{} % we might split it off (module)
\registerctxluafile{node-snp}{autosuffix}
\registerctxluafile{node-tsk}{}
-\registerctxluafile{node-tex}{}
+\registerctxluafile{node-tex}{autosuffix}
\registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used
\registerctxluafile{node-pro}{}
-\registerctxluafile{node-ser}{}
+\registerctxluafile{node-ser}{autosuffix}
\registerctxluafile{node-ext}{}
\registerctxluafile{node-acc}{} % experimental
%registerctxluafile{node-prp}{} % makes no sense (yet)
\registerctxluafile{node-scn}{}
\registerctxluafile{node-syn}{}
-\registerctxluafile{node-par}{}
+\registerctxluafile{node-par}{autosuffix}
\newcount\c_node_tracers_show_box % box number
diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua
index 6a36adf68..cf1d662a3 100644
--- a/tex/context/base/mkiv/node-ltp.lua
+++ b/tex/context/base/mkiv/node-ltp.lua
@@ -281,10 +281,10 @@ local unset_code = nodecodes.unset
local marginkern_code = nodecodes.marginkern
local dir_code = nodecodes.dir
local boundary_code = nodecodes.boundary
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local protrusionboundary_code = nodes.boundarycodes.protrusion
-local leaders_code = nodes.leadercodes.leaders
+local leaders_code = nodes.gluecodes.leaders
local indentlist_code = nodes.listcodes.indent
local ligatureglyph_code = nodes.glyphcodes.ligature
local cancel_code = nodes.dircodes.cancel
@@ -1323,7 +1323,7 @@ do
while current_break do
- -- hm, here we have head == localpar and in the engine it's a temp node
+ -- hm, here we have head == par and in the engine it's a temp node
head = inject_dirs_at_begin_of_line(dirstack,head)
@@ -1463,7 +1463,7 @@ do
p = nil
end
break
- elseif id == localpar_code then
+ elseif id == par_code then
break
elseif id == temp_code then
-- Go on.
@@ -1560,29 +1560,29 @@ do
start = insert_node_before(start,start,ls)
end
if normalize > 0 then
- local localpar = nil
- local localdir = nil
+ local par = nil
+ local dir = nil
local indent = nil
- local localpars = nil
+ local pars = nil
local notflocal = 0
for n, id, subtype in nextnode, start do
if id == hlist_code then
if normalize > 1 and subtype == indentlist_code then
indent = n
end
- elseif id == localpar_code then
+ elseif id == par_code then
if start_of_par(n) then --- maybe subtype check instead
- localpar = n
+ par = n
elseif noflocals then
noflocals = noflocals + 1
- localpars[noflocals] = n
+ pars[noflocals] = n
else
noflocals = 1
- localpars = { n }
+ pars = { n }
end
elseif id == dir_code then
- if localpar and not localdir and subtype(n) == cancel_code then
- localdir = n
+ if par and not dir and subtype(n) == cancel_code then
+ dir = n
end
end
end
@@ -1591,14 +1591,14 @@ do
setattributelist(i,start)
replace_node(indent,i)
end
- if localdir then
- local d = new_direction((getdirection(localpar)))
+ if dir then
+ local d = new_direction((getdirection(par)))
setattributelist(d,start)
- replace_node(localpar,d)
+ replace_node(par,d)
end
- if localpars then
+ if pars then
for i=1,noflocals do
- start = remove_node(start,localpars[i],true)
+ start = remove_node(start,pars[i],true)
end
end
end
@@ -1719,7 +1719,7 @@ do
local id = getid(next)
if id == glyph_code then
break
- elseif id == localpar_code then
+ elseif id == par_code then
-- nothing
elseif id < math_code then
-- messy criterium
@@ -1756,7 +1756,7 @@ par.head = head
if getnext(h) then
report_parbuilders("something is left over")
end
- if getid(h) ~= localpar_code then
+ if getid(h) ~= par_code then
report_parbuilders("no local par node")
end
end
@@ -2454,7 +2454,7 @@ par.head = head
if current then
local id = getid(current)
- if id == localpar_code then
+ if id == par_code then
par.init_internal_left_box = getfield(current,"box_left")
par.init_internal_left_box_width = getfield(current,"box_left_width")
par.internal_pen_inter = getfield(current,"pen_inter")
@@ -2617,7 +2617,7 @@ par.head = head
p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion)
elseif id == dir_code then
par.line_break_dir = checked_line_dir(dirstack,current) or par.line_break_dir
- elseif id == localpar_code then
+ elseif id == par_code then
par.internal_pen_inter = getfield(current,"pen_inter")
par.internal_pen_broken = getfield(current,"pen_broken")
par.internal_left_box = getfield(current,"box_left")
diff --git a/tex/context/base/mkiv/node-nut.lmt b/tex/context/base/mkiv/node-nut.lmt
index d9edf2114..6b9dd803e 100644
--- a/tex/context/base/mkiv/node-nut.lmt
+++ b/tex/context/base/mkiv/node-nut.lmt
@@ -66,6 +66,7 @@ local nuts = {
free = direct.free,
getsynctexfields = direct.get_synctex_fields,
getattr = direct.get_attribute,
+ getattrs = direct.get_attributes,
getattributelist = direct.getattributelist,
getattrlist = direct.getattributelist,
getboth = d_getboth,
@@ -88,8 +89,8 @@ local nuts = {
getheight = direct.getheight,
getid = d_getid,
getkern = direct.getkern,
- getlang = direct.getlang,
- getlanguage = direct.getlang,
+ getlang = direct.getlanguage,-- will become obsolete
+ getlanguage = direct.getlanguage,
getleader = direct.getleader,
getlist = d_getlist,
getnext = d_getnext,
@@ -97,6 +98,7 @@ local nuts = {
getnucleus = direct.getnucleus,
getoffsets = direct.getoffsets,
getorientation = direct.getorientation,
+ getoptions = direct.getoptions,
getpenalty = direct.getpenalty,
getpost = direct.getpost,
getpre = direct.getpre,
@@ -141,11 +143,13 @@ local nuts = {
protect_glyphs = direct.protect_glyphs,
protrusion_skippable = direct.protrusion_skippable,
rangedimensions = direct.rangedimensions,
+ getglyphdimensions = direct.getglyphdimensions,
+ getkerndimension = direct.getkerndimension,
remove = d_remove_node,
reverse = direct.reverse,
set_attribute = direct.set_attribute,
- setsynctexfields = direct.set_synctex_fields,
setattr = direct.set_attribute,
+ setattrs = direct.set_attributes,
setattributelist = direct.setattributelist,
setattrlist = direct.setattributelist,
setboth = direct.setboth,
@@ -167,8 +171,8 @@ local nuts = {
setglyphdata = direct.setglyphdata,
setheight = direct.setheight,
setkern = direct.setkern,
- setlang = direct.setlang,
- setlanguage = direct.setlang,
+ setlang = direct.setlanguage,
+ setlanguage = direct.setlanguage,
setleader = direct.setleader,
setlink = d_setlink,
setlist = direct.setlist,
@@ -176,6 +180,7 @@ local nuts = {
setnucleus = direct.setnucleus,
setoffsets = direct.setoffsets,
setorientation = direct.setorientation,
+ setoptions = direct.setoptions,
setpenalty = direct.setpenalty,
setpost = direct.setpost,
setpre = direct.setpre,
@@ -192,6 +197,7 @@ local nuts = {
setsup = direct.setsup,
setsuppre = direct.setsuppre,
setsurround = direct.setkern,
+ setsynctexfields = direct.set_synctex_fields,
setvalue = direct.setdata, -- obsolete
setwhd = direct.setwhd,
setwidth = direct.setwidth,
@@ -207,6 +213,7 @@ local nuts = {
traverse_glyph = direct.traverse_glyph,
traverse_id = direct.traverse_id,
traverse_list = direct.traverse_list,
+ traverse_content = direct.traverse_content,
unprotect_glyph = direct.unprotect_glyph,
unprotect_glyphs = direct.unprotect_glyphs,
unset_attribute = direct.unset_attribute,
@@ -215,9 +222,9 @@ local nuts = {
vpack = direct.vpack,
writable_spec = direct.writable_spec,
write = direct.write,
+ append = direct.append,
}
-
nodes.nuts = nuts
nodes.is_node = is_node
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 68d238b1a..c73397305 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -309,6 +309,11 @@ nuts.setglyphdata = direct.setglyphdata or function(n,d) set_attribute(n,0,d
nuts.getruledata = direct.getglyphdata and getdata or function(n) return getfield(n,"transform") end
nuts.setruledata = direct.setglyphdata and setdata or function(n,d) return setfield(n,"transform",d) end
+-- maybe some day: [g|s]etglyphoptions and then use attribute for mkiv / generic but not now
+
+nuts.getoptions = direct.getoptions or function() return 0 end
+nuts.setoptions = direct.setoptions or function() end
+
-- so far
nuts.getnucleus = direct.getnucleus
@@ -414,9 +419,9 @@ end
if not nuts.start_of_par then
- local localparcodes = nodes.localparcodes
- local hmodepar_code = localparcodes.vmode_par
- local vmodepar_code = localparcodes.hmode_par
+ local parcodes = nodes.parcodes
+ local hmodepar_code = parcodes.vmode_par
+ local vmodepar_code = parcodes.hmode_par
local getsubtype = nuts.getsubtype
diff --git a/tex/context/base/mkiv/node-par.lmt b/tex/context/base/mkiv/node-par.lmt
new file mode 100644
index 000000000..af3125d23
--- /dev/null
+++ b/tex/context/base/mkiv/node-par.lmt
@@ -0,0 +1,48 @@
+if not modules then modules = { } end modules ['node-par'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local sequencers = utilities.sequencers
+
+-- This are called a lot!
+
+local actions = nodes.tasks.actions("everypar")
+
+local function everypar(head)
+ starttiming(builders)
+ head = actions(head)
+ stoptiming(builders)
+ return head
+end
+
+callbacks.register("insert_par",everypar,"after paragraph start")
+
+local actions = sequencers.new {
+ name = "paragraph",
+ arguments = "mode,indented",
+ returnvalues = "indented",
+ results = "indented",
+}
+
+sequencers.appendgroup(actions,"before") -- user
+sequencers.appendgroup(actions,"system") -- private
+sequencers.appendgroup(actions,"after" ) -- user
+
+local function paragraph(mode,indented)
+ local runner = actions.runner
+ if runner then
+ starttiming(builders)
+ indented = runner(mode,indented)
+ stoptiming(builders)
+ end
+ return indented
+end
+
+callbacks.register("begin_paragraph",paragraph,"before paragraph start")
diff --git a/tex/context/base/mkiv/node-par.lua b/tex/context/base/mkiv/node-par.lua
index d89edf6f4..5a0f0d2e9 100644
--- a/tex/context/base/mkiv/node-par.lua
+++ b/tex/context/base/mkiv/node-par.lua
@@ -25,7 +25,7 @@ end
callbacks.register("insert_local_par",everypar,"after paragraph start")
local actions = sequencers.new {
- name = "newgraf",
+ name = "paragraph",
arguments = "mode,indented",
returnvalues = "indented",
results = "indented",
@@ -35,7 +35,7 @@ sequencers.appendgroup(actions,"before") -- user
sequencers.appendgroup(actions,"system") -- private
sequencers.appendgroup(actions,"after" ) -- user
-local function newgraf(mode,indented)
+local function paragraph(mode,indented)
local runner = actions.runner
if runner then
starttiming(builders)
@@ -45,4 +45,4 @@ local function newgraf(mode,indented)
return indented
end
-callbacks.register("new_graf",newgraf,"before paragraph start")
+callbacks.register("new_graf",paragraph,"before paragraph start")
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index 2e035b2e0..2094fc2c7 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -94,7 +94,7 @@ local glue_code = nodecodes.glue
local glyph_code = nodecodes.glyph
local rule_code = nodecodes.rule
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
@@ -420,7 +420,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
elseif id == dir_code then
local direction, pop = getdirection(current)
txtdir = not pop and direction -- we might need a stack
- elseif id == localpar_code then
+ elseif id == par_code then
if start_of_par(current) then
pardir = getdirection(current)
end
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index c27059003..03de8f843 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -26,7 +26,6 @@ local gluecodes = nodes.gluecodes
local kerncodes = nodes.kerncodes
local rulecodes = nodes.rulecodes
local nodecodes = nodes.nodecodes
-local leadercodes = nodes.leadercodes
local boundarycodes = nodes.boundarycodes
local usercodes = nodes.usercodes
@@ -200,7 +199,7 @@ local correctionskip = register_nut(new_nut(glue_code,gluecodes.correctionski
local temp = register_nut(new_nut(nodecodes.temp,0))
local noad = register_nut(new_nut(nodecodes.noad))
-local delimiter = register_nut(new_nut(nodecodes.delim))
+local delimiter = register_nut(new_nut(nodecodes.delimiter))
local fence = register_nut(new_nut(nodecodes.fence))
local submlist = register_nut(new_nut(nodecodes.submlist))
local accent = register_nut(new_nut(nodecodes.accent))
@@ -214,7 +213,7 @@ local choice = register_nut(new_nut(nodecodes.choice))
local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user))
local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word))
-local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,leadercodes.cleaders) setglue(cleader,0,65536,0,2,0)
+local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0)
-- the dir field needs to be set otherwise crash:
@@ -627,10 +626,10 @@ do
return v
end)
- traversers.node = nodes.traverse (glyph)
- traversers.char = nodes.traverse_char (glyph)
- if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph(glyph) end
- if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end
+ traversers.node = nodes.traverse (glyph)
+ traversers.char = nodes.traverse_char (glyph)
+ if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph (glyph) end
+ if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end
nodes.traversers = traversers
@@ -647,10 +646,11 @@ do
return v
end)
- traversers.node = nuts.traverse (glyph)
- traversers.char = nuts.traverse_char (glyph)
- if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph(glyph) end
- if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end
+ traversers.node = nuts.traverse (glyph)
+ traversers.char = nuts.traverse_char (glyph)
+ if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph (glyph) end
+ if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end
+ if nuts.traverse_content then traversers.content = nuts.traverse_content(glyph) end
nuts.traversers = traversers
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index 830d97ff6..f60fb2406 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -75,7 +75,7 @@ local gluecodes = nodes.gluecodes
local listcodes = nodes.listcodes
local glyph_code = nodecodes.glyph
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local dir_code = nodecodes.dir
local glue_code = nodecodes.glue
local hlist_code = nodecodes.hlist
@@ -588,7 +588,7 @@ function linefillers.handler(head)
else
break
end
- elseif id == localpar_code or id == dir_code then
+ elseif id == par_code or id == dir_code then
-- go on
elseif id == hlist_code then
if getsubtype(head) == indentlist_code then
diff --git a/tex/context/base/mkiv/node-scn.lua b/tex/context/base/mkiv/node-scn.lua
index 055f5e20d..0ec1ba387 100644
--- a/tex/context/base/mkiv/node-scn.lua
+++ b/tex/context/base/mkiv/node-scn.lua
@@ -24,7 +24,6 @@ local setlist = nuts.setlist
local end_of_math = nuts.end_of_math
local nodecodes = nodes.nodecodes
-local leadercodes = nodes.leadercodes
local gluecodes = nodes.gluecodes
local kerncodes = nodes.kerncodes
@@ -43,8 +42,7 @@ local vlist_code = nodecodes.vlist
local userskip_code = gluecodes.userskip
local spaceskip_code = gluecodes.spaceskip
local xspaceskip_code = gluecodes.xspaceskip
-
-local leaders_code = leadercodes.leaders
+local leaders_code = gluecodes.leaders
local fontkern_code = kerncodes.fontkern
diff --git a/tex/context/base/mkiv/node-ser.lmt b/tex/context/base/mkiv/node-ser.lmt
new file mode 100644
index 000000000..0d7f3ccad
--- /dev/null
+++ b/tex/context/base/mkiv/node-ser.lmt
@@ -0,0 +1,285 @@
+if not modules then modules = { } end modules ['node-ser'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tostring = type, tostring
+local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize
+local formatters, format, rep = string.formatters, string.format, string.rep
+
+local allocate = utilities.storage.allocate
+
+local context = context
+local nodes = nodes
+local node = node
+
+local getfields = node.fields
+
+local traverse = nodes.traverse
+local is_node = nodes.is_node
+
+local nodecodes = nodes.nodecodes
+local subtypes = nodes.subtypes
+
+local tonode = nodes.tonode
+local tonut = nodes.tonut
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local f_char = formatters["%U"]
+local f_attr = formatters["<attribute : %i>"]
+local f_recurse = formatters["<recursive : %i>"]
+
+-- flat : don't use next, but indexes
+-- verbose : also add type
+
+local canbezero = {
+ integer = true,
+ dimension = true,
+ number = true,
+}
+
+local canbelist = {
+ attribute = "<attribute>",
+ node = "<node>",
+ token = "<token>",
+ attribute_list = "<attributes>",
+ node_list = "<nodes>",
+ token_list = "<tokens>",
+}
+
+local canbeignored = {
+ prev = "<node>"
+}
+
+local canbechar = {
+ char = true,
+ small_char = true,
+ large_char = true,
+}
+
+local fieldtypes = table.setmetatableindex(function(t,k)
+ local v = getfields(k,true) or false
+ t[k] = v
+ return v
+end)
+
+nodes.fieldtypes = fieldtypes
+
+local function astable(n)
+ n = tonode(n)
+ if n then
+ local fields = fieldtypes[n.id]
+ if fields then
+ local result = { }
+ for field, fieldtype in sortedhash(fields) do
+ local value = n[field]
+ if value then
+ if canbeignored[field] then
+ value = nil
+ elseif canbezero[fieldtype] and value == 0 then
+ value = nil
+ elseif canbelist[fieldtype] then
+ value = canbelist[fieldtype]
+ end
+ if value then
+ result[field] = value
+ end
+ end
+ end
+ local id = n.id
+ if id then
+ id = nodecodes[id]
+ result.id = id
+ local subtype = n.subtype
+ if subtype then
+ local subtypes = subtypes[id]
+ if subtypes then
+ result.subtype = subtypes[subtype]
+ end
+ end
+ end
+ return result
+ end
+ end
+end
+
+nodes.astable = astable
+
+setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end)
+
+local function to_table(n,flat,verbose,noattributes,done)
+ local d = tonut(n)
+ if done[d] then
+ return f_recurse(d)
+ else
+ done[d] = true
+ local fields = fieldtypes[n.id]
+ if fields then
+ local result = { }
+ for field, fieldtype in sortedhash(fields) do
+ local value = n[field]
+ if value then
+ if fieldtype == "attribute_list" or fieldtype == "attribute" then
+ if noattributes then
+ result[value] = canbeignored[value]
+ else
+ result[value] = to_table(value,flat,verbose,noattributes,done)
+ end
+ elseif canbeignored[field] then
+ result[value] = canbeignored[value]
+ elseif not verbose and canbezero[fieldtype] and value == 0 then
+ value = nil
+ elseif canbelist[fieldtype] then
+ if flat then
+ result[value] = canbelist[value]
+ else
+ result[value] = to_table(value,flat,verbose,noattributes,done)
+ end
+ end
+ if value then
+ result[field] = value
+ end
+ end
+ end
+ if verbose then
+ local id = result.id
+ if id then
+ id = nodecodes[id]
+ result.id = id
+ local subtype = result.subtype
+ if subtype then
+ local subtypes = subtypes[id]
+ if subtypes then
+ result.subtype = subtypes[subtype]
+ end
+ end
+ end
+ for k, v in next, canbechar do
+ local v = result[k]
+ if v then
+ result[k] = f_char(v)
+ end
+ end
+ end
+ return result
+ end
+ end
+end
+
+local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true
+ if n then
+ local d = { }
+ if flat then
+ local t, tn = { }, 0
+ while n do
+ tn = tn + 1
+ local nt = to_table(n,flat,verbose,noattributes,d)
+ t[tn] = nt
+ nt.next = nil
+ nt.prev = nil
+ n = n.next
+ end
+ done = nil
+ return t
+ else
+ local t = to_table(n,flat,verbose,noattributes,d)
+ local n = n.next
+ if n then
+ t.next = totable(n,flat,verbose,noattributes,d)
+ end
+ return t
+ end
+ else
+ return { }
+ end
+end
+
+nodes.totable = function(n,...) return totable(tonode(n),...) end
+nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list
+
+local function key(k)
+ return ((type(k) == "number") and "["..k.."]") or k
+end
+
+function nodes.serialize(root,flat,verbose,noattributes,name)
+ return serialize(totable(tonode(root),flat,verbose,noattributes),name)
+end
+
+function nodes.serializebox(n,flat,verbose,noattributes,name)
+ return serialize(totable(tex.box[n],flat,verbose,noattributes),name)
+end
+
+function nodes.visualizebox(n,flat,verbose,noattributes,name)
+ context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name)
+end
+
+function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway
+ head = tonode(head)
+ if not n then
+ context.starttyping(true)
+ end
+ while head do
+ local id = head.id
+ context(rep(" ",n or 0) .. tostring(head) .. "\n")
+ if id == hlist_code or id == vlist_code then
+ nodes.list(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+ if not n then
+ context.stoptyping(true)
+ end
+end
+
+function nodes.print(head,n)
+ head = tonode(head)
+ while head do
+ local id = head.id
+ logs.writer(string.formatters["%w%S"],n or 0,head)
+ if id == hlist_code or id == vlist_code then
+ nodes.print(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+end
+
+-- quick hack, nicer is to have a proper expand per node type already prepared
+
+local function apply(n,action)
+ while n do
+ action(n)
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ apply(n.list,action)
+ end
+ n = n.next
+ end
+end
+
+nodes.apply = apply
+
+local nuts = nodes.nuts
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getnext = nuts.getnext
+
+local function apply(n,action)
+ while n do
+ action(n)
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ local list = getlist(n,action)
+ if list then
+ apply(list,action)
+ end
+ end
+ n = getnext(n)
+ end
+end
+
+nuts.apply = apply
diff --git a/tex/context/base/mkiv/node-tex.lmt b/tex/context/base/mkiv/node-tex.lmt
new file mode 100644
index 000000000..aae084740
--- /dev/null
+++ b/tex/context/base/mkiv/node-tex.lmt
@@ -0,0 +1,39 @@
+if not modules then modules = { } end modules ['node-tex'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+builders = builders or { }
+local kernel = builders.kernel or { }
+builders.kernel = kernel
+
+local nuts = nodes.nuts
+
+local hyphenate = language.hyphenate
+
+local hyphenating = nuts.hyphenating
+local ligaturing = nuts.ligaturing
+local kerning = nuts.kerning
+
+function kernel.hyphenation(head)
+ return (hyphenate(head)) -- nodes !
+end
+
+function kernel.hyphenating(head)
+ return (hyphenating(head))
+end
+
+function kernel.ligaturing(head)
+ return (ligaturing(head))
+end
+
+function kernel.kerning(head)
+ return (kerning(head))
+end
+
+callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere")
+callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere")
+callbacks.register('kerning' , false, "normal kerning routine, called elsewhere")
diff --git a/tex/context/base/mkiv/node-tex.lua b/tex/context/base/mkiv/node-tex.lua
index 5857fd2e6..cda6ff132 100644
--- a/tex/context/base/mkiv/node-tex.lua
+++ b/tex/context/base/mkiv/node-tex.lua
@@ -16,7 +16,6 @@ local hyphenate = lang.hyphenate
local hyphenating = nuts.hyphenating
local ligaturing = nuts.ligaturing
local kerning = nuts.kerning
-local cleanup = nuts.flush_components
function kernel.hyphenation(head)
return (hyphenate(head)) -- nodes !
@@ -34,14 +33,6 @@ function kernel.kerning(head)
return (kerning(head))
end
-if cleanup then
-
- function kernel.cleanup(head)
- return (cleanup(head))
- end
-
-end
-
callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere")
callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere")
callbacks.register('kerning' , false, "normal kerning routine, called elsewhere")
diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua
index 2ebfaff12..a86dfb620 100644
--- a/tex/context/base/mkiv/node-tra.lua
+++ b/tex/context/base/mkiv/node-tra.lua
@@ -77,7 +77,7 @@ local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
local rule_code = nodecodes.rule
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local whatsit_code = nodecodes.whatsit
local dimenfactors = number.dimenfactors
@@ -115,19 +115,6 @@ function nodes.handlers.checkglyphs(head,message)
return false
end
-function nodes.handlers.checkforleaks(sparse)
- local l = { }
- local q = used_nodes()
- for p, id in nextnode, q do
- local s = table.serialize(nodes.astable(p,sparse),nodecodes[id])
- l[s] = (l[s] or 0) + 1
- end
- flush_list(q)
- for k, v in next, l do
- report_nodes("%s * %s",v,k)
- end
-end
-
local fontcharacters -- = fonts.hashes.descriptions
local function tosequence(start,stop,compact)
@@ -167,7 +154,7 @@ local function tosequence(start,stop,compact)
elseif id == dir_code then
local d, p = getdirection(start)
n = n + 1 ; t[n] = "[<" .. (p and "-" or "+") .. d .. ">]" -- todo l2r etc
- elseif id == localpar_code and start_of_par(current) then
+ elseif id == par_code and start_of_par(current) then
n = n + 1 ; t[n] = "[<" .. getdirection(start) .. ">]" -- todo l2r etc
elseif compact then
n = n + 1 ; t[n] = "[]"
@@ -325,14 +312,6 @@ local function showsimplelist(h,depth,n)
end
end
--- \startluacode
--- callbacks.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end)
--- \stopluacode
--- \vbox{b\footnote{n}a}
--- \startluacode
--- callbacks.register('buildpage_filter',nil)
--- \stopluacode
-
nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
local function listtoutf(h,joiner,textonly,last,nodisc)
diff --git a/tex/context/base/mkiv/pack-box.mkxl b/tex/context/base/mkiv/pack-box.mkxl
new file mode 100644
index 000000000..2f52939ce
--- /dev/null
+++ b/tex/context/base/mkiv/pack-box.mkxl
@@ -0,0 +1,1114 @@
+%D \module
+%D [ file=pack-box,
+%D version=2002.04.12,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Boxes}
+
+%D This module contains all kind of macros for moving content around. Many
+%D macros here come from other modules, but depencies made it more clear
+%D to isolate them. We invite users to document the macros. They can be
+%D handy shortcuts for otherwise complex tasks.
+
+\unprotect
+
+%D We need to set the size, else we get dimensions depending on the content,
+%D which in itself is ok, but can lead to loops due to rounding errors (happened
+%D in demo-obv).
+
+% \definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+% \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+% \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+% \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
+
+\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
+\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
+\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
+\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
+
+\permanent\protected\def\internaltextoverlay#1% will become more generic and installable
+ {\startoverlay % i.e. probably an overlay by itself
+ {\positionregionoverlay\textanchor{\v!text#1}}% see later
+ {\composedlayer {\v!text#1}}%
+ \stopoverlay}
+
+\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
+\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
+\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
+\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
+
+\installcorenamespace {anchor}
+
+% produces a box too
+%
+% \anchor[text-1][preset=lefttop][framed settings]{HELLO WORLD}
+
+\permanent\tolerant\protected\def\defineanchor[#1]#*[#2]#*[#3]#*[#4]% name targetlayer layersetting framedsetting
+ {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}}
+
+\def\pack_anchors_process_defined#1#2#3%
+ {\tolerant\def\pack_anchors_process_defined_indeed[##1]##*[##2]%
+ {\ifarguments
+ \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}%
+ \or
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}%
+ \or
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}%
+ \fi
+ \next}% picks up a box
+ \pack_anchors_process_defined_indeed}
+
+\protected\def\anchor[#1]%
+ {\begingroup
+ \edef\currentanchor{#1}%
+ \ifcsname\??anchor\currentanchor\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\pack_anchor_notdefined
+ \fi}
+
+\tolerant\def\pack_anchor_notdefined[#1]#*[#2]%
+ {\ifarguments
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\pack_anchor_notdefined_one
+ \else
+ \expandafter\pack_anchor_notdefined_two
+ \fi{#1}{#2}}
+
+\def\pack_anchor_notdefined_one #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#1}}\vbox}
+\def\pack_anchor_notdefined_two #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#2}}\vbox}
+\def\pack_anchors_process_indeed#1#2#3{\dowithnextbox{\pack_anchors_process_finish {#1}{#2}{#3}}\vbox}
+
+\newbox \b_pack_anchors
+\newdimen\d_pack_anchors_width
+\newdimen\d_pack_anchors_height
+\newdimen\d_pack_anchors_depth
+
+% \definelayer[anchor]
+
+\newcount\c_pack_anchors_n
+\newtoks \t_pack_anchors_flush
+
+\protected\def\pack_anchors_register#1#2%
+ {\global\advance\c_pack_anchors_n\plusone
+ \pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]%
+ \putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors
+% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}%
+ \doglobal\appendetoks
+ \pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}%
+ \to \t_pack_anchors_flush
+ \glet\pack_anchors_flush_all\pack_anchors_flush_all_indeed}
+
+\protected\def\pack_anchors_flush#1#2#3%
+ {\doifelseboxincache\v!anchor{#1}
+ {\doifelsereferencefound{\v!layer:\v!anchor:#1}
+ {\ifnum\currentreferencerealpage=\realpageno\relax
+ \setlayer[#2][#3,\c!position=\v!no]{\directboxfromcache\v!anchor{#1}}%
+ \else
+ \donetrue
+ \fi
+ }\donetrue}%
+ \donetrue}%
+
+\protected\def\pack_anchors_flush_all_indeed
+ {\donefalse
+ \the\t_pack_anchors_flush
+ \ifdone\else
+ \global\t_pack_anchors_flush\emptytoks
+ \glet\pack_anchors_flush_all\relax
+ \fi}
+
+\let\pack_anchors_flush_all\relax
+
+\appendtoks
+ \pack_anchors_flush_all
+\to \everybeforepagebody
+
+\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy
+ {\checkpositionoverlays
+ \setbox\b_pack_anchors\box\nextbox
+ \framed % could be a predefined framed but used seldom
+ [\c!offset=\v!overlay,\c!frame=\v!off,#3]
+ {\pack_anchors_register{#1}{#2}%
+ \novrule % hm, not needed as we frame the size (but kind of default)
+ \s!width \wd\b_pack_anchors
+ \s!height\ht\b_pack_anchors
+ \s!depth \dp\b_pack_anchors}%
+ \endgroup}
+
+% \setlayeranchored[text-1][preset=lefttop]{HELLO WORLD} produces a simple (empty) hbox
+% synchronizes per page
+
+\permanent\tolerant\protected\def\setlayeranchored[#1]#*[#2]%
+ {\begingroup
+ \ifarguments
+ \dowithnextbox
+ {\endgroup}%
+ \or
+ \dowithnextbox
+ {\checkpositionoverlays
+ \setbox\b_pack_anchors\box\nextbox
+ \dontleavehmode\hpack{\pack_anchors_register{#1}{#2}}%
+ \endgroup}%
+ \fi
+ \hbox}
+
+% collectors
+
+\installcorenamespace{collectorbox}
+\installcorenamespace{collector}
+
+\installcommandhandler \??collector {collector} \??collector
+
+\setupcollector
+ [\c!state=\v!start,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!offset=\zeropoint,
+ \c!rotation=, % geen 0 !
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!location=rb,
+ \c!corner=]
+
+\appendtoks
+ \ifcsname\??collectorbox\currentcollector\endcsname \else
+ \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname
+ \fi
+\to \everydefinecollector
+
+\permanent\protected\def\resetcollector[#1]%
+ {\ifcsname\??collectorbox#1\endcsname
+ \global\setbox\lastnamedcs\emptybox
+ \fi}
+
+\newconditional\c_pack_boxes_collector_valid_box
+
+\let\b_pack_boxes_collector\scratchbox
+
+\def\pack_boxes_collector_check_box#1%
+ {\edef\currentcollector{#1}%
+ \ifcsname\??collectorbox\currentcollector\endcsname
+ \settrue\c_pack_boxes_collector_valid_box
+ \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs
+ \else
+ \setfalse\c_pack_boxes_collector_valid_box
+ \writestatus{collector}{unknown collector \currentcollector}%
+ \fi}
+
+\permanent\tolerant\protected\def\setcollector[#1]#*[#2]% todo: keep reference point
+ {\bgroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \setupcurrentcollector[#2]%
+ \expandafter\pack_boxes_collector_yes
+ \else
+ \expandafter\pack_boxes_collector_nop
+ \fi}
+
+\def\pack_boxes_collector_yes
+ {\forgetall
+ \dontcomplain
+ \dowithnextboxcs\pack_boxes_collector_finish\hbox}
+
+\let\pack_boxes_collector_nop\egroup
+
+\installcorenamespace{collectorcorners}
+
+\setvalue{\??collectorcorners\v!middle}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position.5\d_pack_layers_x_size
+ \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position.5\d_pack_layers_y_size
+ \fi}
+
+\setvalue{\??collectorcorners\v!bottom}%
+ {\ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position-\d_pack_layers_y_size
+ \d_pack_layers_y_position-\d_pack_layers_y_position
+ \fi}
+
+\setvalue{\??collectorcorners\v!right}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position-\d_pack_layers_x_size
+ \d_pack_layers_x_position-\d_pack_layers_x_position
+ \fi}
+
+\def\pack_boxes_collector_check_corner#1%
+ {\ifcsname\??collectorcorners#1\endcsname
+ \lastnamedcs
+ \fi}
+
+\def\pack_boxes_collector_finish
+ {\edef\p_collector_rotation{\collectorparameter\c!rotation}%
+ \edef\p_collector_corner {\collectorparameter\c!corner}%
+ \ifx\p_collector_rotation\empty \else
+ \setbox\nextbox\hpack
+ {\rotate
+ [\c!location=\v!high,
+ \c!rotation=\p_collector_rotation]
+ {\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax
+ \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax
+ \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner
+ \setbox\nextbox\hpack
+ {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}%
+ \boxmaxdepth\zeropoint % really needed, nice example
+ \global\advance\boxhdisplacement\d_pack_layers_x_position
+ \ifdim\boxhdisplacement<\zeropoint
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\kern-\boxhdisplacement
+ \box\b_pack_boxes_collector}%
+ \fi
+ \global\advance\boxvdisplacement\d_pack_layers_y_position
+ \ifdim\boxvdisplacement<\zeropoint
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\lower-\boxvdisplacement
+ \box\b_pack_boxes_collector}%
+ \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\box\b_pack_boxes_collector
+ \kern\dimexpr
+ -\d_pack_layers_x_size
+ +\d_pack_layers_x_position
+ \ifdim\boxhdisplacement<\zeropoint
+ -\boxhdisplacement
+ \fi
+ \relax
+ \lower\d_pack_layers_y_position\hpack
+ {\ifdim\boxvdisplacement<\zeropoint
+ \lower-\boxvdisplacement
+ \fi
+ \box\nextbox}}%
+ % combine height and depth into depth only (later flushed as height)
+ \global\setbox\b_pack_boxes_collector\hpack
+ {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}%
+ % just to be sure
+ \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size
+ \wd\b_pack_boxes_collector\d_pack_layers_x_size
+ \fi
+ \egroup}
+
+\permanent\protected\def\flushcollector[#1]%
+ {\bgroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \edef\p_collector_state{\collectorparameter\c!state}%
+ \ifx\p_collector_state\v!stop \else
+ \vpack{\hpack{\raise
+ \dp\b_pack_boxes_collector
+ \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}%
+ \fi
+ \fi
+ \egroup}
+
+\permanent\protected\def\composedcollector#1% no [], handy as argument
+ {\flushcollector[#1]}
+
+\permanent\tolerant\protected\def\adaptcollector[#1]#*[#2]% % a typical case where \global\wd looks better in the code
+ {\begingroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \letcollectorparameter\c!voffset\zeropoint
+ \letcollectorparameter\h!voffset\zeropoint
+ \setupcurrentcollector[#2]%
+ \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax
+ \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax
+ \fi
+ \endgroup}
+
+%\definecollector[test]
+%\setcollector[test]
+% [location=rb]
+% {\externalfigure[koe][frame=on,width=3cm]}
+%\setcollector[test]
+% [corner={right,bottom},location={left,top}]
+% {\framed{gans}}
+%\composedcollector{test}
+
+\definecollector
+ [caption]
+
+\permanent\tolerant\protected\def\collectedtext[#1]#*[#2]% for captions
+ {\pack_boxes_collector_text[#1][#2]}
+
+\def\pack_boxes_collector_text[#1][#2]#3% #3 is mandate so no tolerant here, so still two step
+ {\bgroup
+ \dowithnextbox
+ {\setcollector
+ [caption]
+ {\box\nextbox}%
+ \setcollector
+ [caption][#1]%
+ {\letdummyparameter\c!style\empty
+ \letdummyparameter\c!color\empty
+ \getdummyparameters[#2]%
+ \dousestyleparameter{\directdummyparameter\c!style}%
+ \setupinterlinespace
+ \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}%
+ \composedcollector{caption}%
+ \egroup}%
+ \hbox}
+
+% \collectedtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\installcorenamespace {layeredtext}
+\installcorenamespace {layeredtextlayer}
+\installcorenamespace {layeredtextframed}
+
+\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext
+
+\newdimen\d_pack_layeredtexts_width
+\newdimen\d_pack_layeredtexts_height
+
+\definelayer % private
+ [\??layeredtextlayer]
+
+\setuplayer % private
+ [\??layeredtextlayer]
+ [\c!width=\d_pack_layeredtexts_width,
+ \c!height=\d_pack_layeredtexts_height]
+
+\defineframed % private
+ [\??layeredtextframed]
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!background={\v!foreground,\??layeredtextlayer},
+ \c!width=\d_pack_layeredtexts_width,
+ \c!height=\d_pack_layeredtexts_height]
+
+\setuplayeredtext % public (the attached data, usually small stuff, not the main thing)
+ [\c!frame=\v!overlay,
+ \c!color=,
+ \c!style=,
+ \c!foregroundcolor=\layeredtextparameter\c!color,
+ \c!foregroundstyle=\layeredtextparameter\c!style]
+
+\permanent\tolerant\protected\def\placelayeredtext[#1]#*[#2]#*[#3]#4% tag layersettings content(framed)settings content
+ {\bgroup
+ \edef\currentlayeredtext{#1}%
+ \checklayeredtextparent % bonus
+ \setupcurrentlayeredtext[#3]%
+ \dowithnextbox
+ {\d_pack_layeredtexts_width \wd\nextbox
+ \d_pack_layeredtexts_height\ht\nextbox
+ \begingroup % preserve \nextbox
+ \setlayer
+ [\??layeredtextlayer]%
+ [#2]%
+ {\setfalse\fontattributeisset
+ \uselayeredtextstyleparameter\c!style
+ \ifconditional\fontattributeisset
+ \setupinterlinespace
+ \fi
+ \inheritedlayeredtextframed{#4}}%
+ \endgroup
+ \placeframed[\??layeredtextframed]{\flushnextbox}%
+ \egroup}%
+ \hbox}
+
+\permanent\protected\def\layeredtext
+ {\placelayeredtext[]}
+
+% \layeredtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\permanent\tolerant\protected\def\ornamenttext[#1]#*[#2]% takes another argument
+ {\bgroup
+ \doifelseassignment{#1}
+ {\letdummyparameter\c!alternative\v!a
+ \getdummyparameters[#1]%
+ \doifelse{\directdummyparameter\c!alternative}\v!a
+ {\egroup\collectedtext}%
+ {\egroup\layeredtext }%
+ [#1][#2]}%
+ {\egroup\getvalue{#1}}}
+
+\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]%
+ {\setuvalue{#1}{\pack_ornament_text[#2][#3]}}
+
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex,alternative=b]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=a]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{photo}{\externalfigure[molen][width=3cm]}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=b]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
+
+\newcount\c_pack_boxes_bleeds
+
+\installcorenamespace {bleeding}
+
+\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding
+
+\setupbleeding
+ [\c!location=l,
+ \c!stretch=\v!yes,
+ \c!width=3cm,
+ \c!height=3cm,
+ \c!offset=2mm,
+ \c!page=\v!no,
+ \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset
+ \c!hoffset=\scratchoffset] % which often saves one resolve
+
+\def\bleedwidth {\the\hsize} % these are global !
+\def\bleedheight{\the\vsize} % these are global !
+
+\newconditional\c_pack_boxes_l
+\newconditional\c_pack_boxes_r
+\newconditional\c_pack_boxes_t
+\newconditional\c_pack_boxes_b
+
+\installcorenamespace{bleedinglocation}
+
+\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+
+\permanent\tolerant\protected\def\bleed[#1]%
+ {\hbox\bgroup
+ \global\advance\c_pack_boxes_bleeds\plusone
+ %
+ \xdef\bleedwidth {\the\hsize}%
+ \xdef\bleedheight{\the\vsize}%
+ %
+ \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}%
+ \edef\currentpageposition{page:0}% todo: per page
+ %
+ \setupcurrentbleeding[#1]%
+ %
+ \scratchwidth \bleedingparameter\c!width
+ \scratchheight \bleedingparameter\c!height
+ \scratchoffset \bleedingparameter\c!offset
+ \scratchhoffset\bleedingparameter\c!hoffset
+ \scratchvoffset\bleedingparameter\c!voffset
+ %
+ \setfalse\c_pack_boxes_l % left
+ \setfalse\c_pack_boxes_r % right
+ \setfalse\c_pack_boxes_t % top
+ \setfalse\c_pack_boxes_b % bottom
+ %
+ \csname\??bleedinglocation\bleedingparameter\c!location\endcsname
+ %
+ \doifelse{\bleedingparameter\c!stretch}\v!yes\donetrue\donefalse
+ %
+ \xdef\bleedwidth{\the\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_l
+ \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition
+ \else\ifconditional\c_pack_boxes_r
+ \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked
+ \else
+ \scratchwidth
+ \fi\fi
+ \else
+ \scratchwidth
+ \fi+\scratchhoffset
+ \relax}%
+ \xdef\bleedheight{\the\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_t
+ \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked
+ \else\ifconditional\c_pack_boxes_b
+ \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition + \MPh\currentbgposition % not checked (\MPh added)
+ \else
+ \scratchheight
+ \fi\fi
+ \else
+ \scratchheight
+ \fi+\scratchvoffset
+ \relax}%
+ \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox}
+
+\def\pack_boxes_bleed_settings
+ {\hsize\bleedwidth
+ \vsize\bleedheight}
+
+\def\pack_boxes_bleed_finish
+ {\doif{\bleedingparameter\c!page}\v!yes
+ {\setbox\nextbox\topskippedbox{\box\nextbox}}%
+ \setbox\nextbox\hpack to \scratchwidth
+ {\ifconditional\c_pack_boxes_l\hss\fi
+ \box\nextbox
+ \ifconditional\c_pack_boxes_r\hss\fi}%
+ \ifconditional\c_pack_boxes_b
+ \setbox\nextbox\hpack
+ {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}%
+ \fi
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\zeropoint
+ \ifdone
+ \hpos\currentbgposition{\box\nextbox}%
+ \else
+ \box\nextbox
+ \fi
+ \egroup}
+
+\defineexternalfigure
+ [bleed] % should be \v!bleed
+ [\c!width=\bleedwidth,
+ \c!height=\bleedheight]
+
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[right]{none}
+% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure
+% [top,none]
+% {} % no caption
+% {\bleed
+% [hoffset=-\backspace,
+% voffset=3mm,
+% width=0cm,
+% height=6\lineheight,
+% page=yes, % correct for topskip
+% location=lt]
+% {\externalfigure[koe][bleed][frame=on]}}
+
+% \setlayerframed[layer id][layer settings][framed setting]{data}
+% \setlayerframed[layer id][combined settings]{data}
+
+% tricky: offsets apply to both the layer and the framed; it makes sense to
+% only apply the offset to ...
+
+\permanent\tolerant\protected\def\setlayerframed[#1]#*[#2]#*[#3]
+ {\ifarguments
+ % error
+ \or
+ \expandafter\pack_layers_set_framed_s
+ \or
+ \expandafter\pack_layers_set_framed_d
+ \or
+ \expandafter\pack_layers_set_framed_t
+ \fi[#1][#2][#3]}
+
+\def\pack_layers_set_framed_s[#1][#2][#3]%
+ {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]%
+ \normalframedwithsettings[\c!location=\v!normal]} % different kind of location
+
+\def\pack_layers_set_framed_d[#1][#2][#3]%
+ {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]%
+ \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location
+
+\def\pack_layers_set_framed_t[#1][#2][#3]%
+ {\setlayer[#1][#2]%
+ \normalframedwithsettings[#3]}
+
+\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#3]%
+ {\bgroup
+ \letdummyparameter\c!align\empty
+ \letdummyparameter\c!width\hsize
+ \letdummyparameter\c!color\empty
+ \letdummyparameter\c!style\empty
+ \getdummyparameters[#3]%
+ \dowithnextboxcontent
+ {\forgetall
+ \hsize\directdummyparameter\c!width
+ \usealignparameter\directdummyparameter
+ \dousestyleparameter{\directdummyparameter\c!style}}
+ {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color
+ \egroup}%
+ \vtop}
+
+% \setupbackgrounds
+% [page]
+% [background=pagefigures]
+%
+% \definelayer
+% [pagefigures]
+% [x=-2mm,
+% y=-2mm,
+% width=\paperwidth,
+% height=\paperheight]
+%
+% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}]
+% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}]
+% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}]
+% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
+% \definelayerpreset [middle] [corner=middle,location=middle]
+%
+% \setlayer[pagefigures][preset=lefttop]
+% \setlayer[pagefigures][preset=righttop]
+% \setlayer[pagefigures][preset=leftbottom]
+% \setlayer[pagefigures][preset=rightbottom]
+
+\definelayerpreset
+ [\v!left\v!top]
+ [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
+
+\definelayerpreset
+ [\v!right\v!top]
+ [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
+
+\definelayerpreset
+ [\v!left\v!bottom]
+ [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!bottom]
+ [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!middle]
+ [\c!corner=\v!middle,\c!location=\v!middle]
+
+\definelayerpreset
+ [\v!middle\v!top]
+ [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!bottom]
+ [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!left]
+ [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!right]
+ [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
+
+% left and right hanging:
+
+\definelayerpreset
+ [\v!left\v!top\v!left]
+ [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!top\v!right]
+ [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}]
+
+\installcorenamespace{alignedboxes}
+
+\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
+\permanent\tolerant\protected\def\aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
+
+\def\pack_boxes_aligned_finish
+ {\ifcsname\??alignedboxes\serializedcommalist\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\middlebox
+ \fi{\flushnextbox}%
+ \egroup}
+
+\letvalue{\??alignedboxes }\middlebox
+\letvalue{\??alignedboxes\v!middle }\middlebox
+\letvalue{\??alignedboxes\v!middle\v!middle}\middlebox
+\letvalue{\??alignedboxes\v!left }\leftbox
+\letvalue{\??alignedboxes\v!left \v!top }\lefttopbox
+\letvalue{\??alignedboxes\v!left \v!bottom}\leftbottombox
+\letvalue{\??alignedboxes\v!right }\rightbox
+\letvalue{\??alignedboxes\v!right \v!top }\righttopbox
+\letvalue{\??alignedboxes\v!right \v!bottom}\rightbottombox
+\letvalue{\??alignedboxes\v!bottom }\bottombox
+\letvalue{\??alignedboxes\v!bottom\v!left }\bottomleftbox
+\letvalue{\??alignedboxes\v!bottom\v!right }\bottomrightbox
+\letvalue{\??alignedboxes\v!top }\topbox
+\letvalue{\??alignedboxes\v!top \v!left }\topleftbox
+\letvalue{\??alignedboxes\v!top \v!right }\toprightbox
+\letvalue{\??alignedboxes\v!line }\baselinemiddlebox % \v!grid is taken
+\letvalue{\??alignedboxes\v!line \v!left }\baselineleftbox
+\letvalue{\??alignedboxes\v!line \v!middle}\baselinemiddlebox
+\letvalue{\??alignedboxes\v!line \v!right }\baselinerightbox
+\letvalue{\??alignedboxes c}\middlebox
+\letvalue{\??alignedboxes l}\leftbox
+\letvalue{\??alignedboxes r}\rightbox
+\letvalue{\??alignedboxes b}\bottombox
+\letvalue{\??alignedboxes t}\topbox
+\letvalue{\??alignedboxes lt}\lefttopbox
+\letvalue{\??alignedboxes lb}\leftbottombox
+\letvalue{\??alignedboxes rt}\righttopbox
+\letvalue{\??alignedboxes rb}\rightbottombox
+\letvalue{\??alignedboxes tl}\topleftbox
+\letvalue{\??alignedboxes bl}\bottomleftbox
+\letvalue{\??alignedboxes tr}\toprightbox
+\letvalue{\??alignedboxes br}\bottomrightbox
+\letvalue{\??alignedboxes m}\middlebox
+\letvalue{\??alignedboxes g}\baselinemiddlebox
+\letvalue{\??alignedboxes gl}\baselineleftbox
+\letvalue{\??alignedboxes gc}\baselinemiddlebox
+\letvalue{\??alignedboxes gr}\baselinerightbox
+
+% left/right/top/bottomoffset -> dimensions change
+% x/y | method=fixed -> dimensions don't change
+
+\installcorenamespace{offsetbox}
+
+\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox
+
+\setupoffsetbox
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\wd\nextbox,
+ \c!height=\ht\nextbox,
+ \c!depth=\dp\nextbox,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=]
+
+\aliased\let\setupoffset\setupoffsetbox
+
+\permanent\tolerant\protected\def\offsetbox[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish}
+
+\permanent\tolerant\protected\def\offset[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish\hbox}
+
+\newcount\c_pack_boxes_offset_level
+
+\def\pack_boxes_offset_check
+ {\advance\c_pack_boxes_offset_level\plusone
+ \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}%
+ \checkoffsetboxparent
+ \setupcurrentoffsetbox}
+
+\def\pack_boxes_offsetfinish
+ {\donefalse
+ \scratchxposition \offsetboxparameter\c!x
+ \scratchyposition \offsetboxparameter\c!y
+ \scratchleftoffset \offsetboxparameter\c!leftoffset
+ \scratchrightoffset \offsetboxparameter\c!rightoffset
+ \scratchtopoffset \offsetboxparameter\c!topoffset
+ \scratchbottomoffset\offsetboxparameter\c!bottomoffset
+ \relax % really needed
+ \ifzeropt\scratchleftoffset \else\donetrue\fi
+ \ifzeropt\scratchrightoffset \else\donetrue\fi
+ \ifzeropt\scratchtopoffset \else\donetrue\fi
+ \ifzeropt\scratchbottomoffset\else\donetrue\fi
+ \ifdone
+ \edef\p_method{\offsetboxparameter\c!method}%
+ \ifx\p_method\v!fixed % new
+ \ifzeropt\scratchleftoffset
+ \ifzeropt\scratchrightoffset \else
+ \scratchxposition-\scratchrightoffset
+ \scratchrightoffset\zeropoint
+ \fi
+ \else
+ \scratchxposition\scratchleftoffset
+ \scratchleftoffset\zeropoint
+ \fi
+ \ifzeropt\scratchtopoffset
+ \ifzeropt\scratchbottomoffset \else
+ \scratchyposition-\scratchbottomoffset
+ \scratchbottomoffset\zeropoint
+ \fi
+ \else
+ \scratchyposition\scratchtopoffset
+ \scratchtopoffset\zeropoint
+ \fi
+ \donefalse
+ \fi
+ \fi
+ \ifdone
+ \setbox\nextbox\vpack
+ {\forgetall % already done
+ \offinterlineskip
+ \kern\scratchtopoffset
+ \hpack
+ {\kern\scratchleftoffset
+ \box\nextbox
+ \kern\scratchrightoffset}%
+ \kern\scratchbottomoffset}%
+ \ht\nextbox\htdp\nextbox
+ \dp\nextbox\zeropoint
+ \fi
+ \scratchwidth \offsetboxparameter\c!width
+ \scratchheight\offsetboxparameter\c!height
+ \scratchdepth \offsetboxparameter\c!depth
+ \edef\p_location{\offsetboxparameter\c!location}%
+ \setbox\nextbox\hpack
+ {\kern\scratchxposition
+ \lower\scratchyposition\hpack
+ {\ifx\p_location\empty
+ \box\nextbox
+ \else
+ \alignedbox[\p_location]\hpack{\box\nextbox}%
+ \fi}}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+%D \starttyping
+%D \framed[offset=overlay]{\offset[leftoffset=1cm]
+%D {\framed[offset=overlay]{\offset[rightoffset=1cm]
+%D {\externalfigure[koe][width=1cm]}}}}
+%D
+%D \blank
+%D
+%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank
+%D \stoptyping
+
+% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
+%
+% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte
+
+% Some old code:
+%
+% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+%
+% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+%
+% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
+% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
+% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
+
+\def\pack_boxes_tabbed#1#2#3#4%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hpack{#3}%
+ \hpack to \wd\scratchbox{#1#4#2}%
+ \endgroup}
+
+\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss}
+\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss \relax}
+\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss \hss}
+
+\let\mtabbed\ctabbed
+
+% to be documented
+
+\permanent\protected\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
+ {\hpack\bgroup
+ \letdummyparameter\c!width \zeropoint
+ \letdummyparameter\c!height\zeropoint
+ \letdummyparameter\c!depth \zeropoint
+ \getdummyparameters[#1]%
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox\directdummyparameter\c!width
+ \ht\scratchbox\directdummyparameter\c!height
+ \dp\scratchbox\directdummyparameter\c!depth
+ \box\scratchbox
+ \egroup}
+
+% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
+
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
+%
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
+% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
+
+\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \scratchcounter#1\relax
+ \scratchwidth #2\relax
+ \scratchheight #3\relax
+ \dowithnextboxcs\pack_boxes_background_image\hbox}
+
+\def\pack_boxes_background_image
+ {\offinterlineskip
+ \ifcase\scratchcounter
+ % just one
+ \else
+ \scratchdimen\scratchwidth \divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax
+ \scratchdimen\scratchheight\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax
+ % to be considered: methods
+ \ifcase\scratchcounter
+ \or % x and y
+ \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
+ \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+ \or % x
+ \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
+ \or % y
+ \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+ \fi
+ \fi
+ \ifdim\wd\nextbox>\scratchwidth
+ \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}%
+ \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+ \fi
+ \ifdim\ht\nextbox>\scratchheight
+ \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}%
+ \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+ \fi
+ \box\nextbox
+ \egroup}
+
+\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \scratchcounter#1\relax
+ \scratchwidth #2\relax
+ \scratchheight #3\relax
+ \dowithnextboxcs\pack_boxes_background_image_fill\hbox}
+
+\def\pack_boxes_background_image_fill
+ {\offinterlineskip
+ \setbox\nextbox\hpack\bgroup
+ \ifdim\scratchwidth>\scratchheight
+ \scale[\c!width=\the\scratchwidth]{\box\nextbox}%
+ \else
+ \scale[\c!height=\the\scratchheight]{\box\nextbox}%
+ \fi
+ \egroup
+ \ifdim\wd\nextbox>\scratchwidth
+ \setbox\nextbox\hpack to \scratchwidth
+ {\ifcase\scratchcounter
+ \hss\box\nextbox\hss
+ \or
+ \box\nextbox\hss
+ \or
+ \hss\box\nextbox
+ \else
+ \hss\box\nextbox\hss
+ \fi}%
+ \setbox\nextbox\hpack
+ {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+ \fi
+ \ifdim\ht\nextbox>\scratchheight
+ \setbox\nextbox\vpack to \scratchheight
+ {\ifcase\scratchcounter
+ \vss\box\nextbox\vss
+ \or
+ \box\nextbox\vss
+ \or
+ \vss\box\nextbox
+ \else
+ \vss\box\nextbox\vss
+ \fi}%
+ \setbox\nextbox\hpack
+ {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+ \fi
+ \box\nextbox
+ \egroup}
+
+\permanent\protected\def\overlayimage#1%
+ {\vpack to \overlayheight\bgroup
+ \vss
+ \hpack to \overlaywidth\bgroup
+ \hss
+ \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]%
+ \hss
+ \egroup
+ \vss
+ \egroup}
+
+\permanent\protected\def\clippedoverlayimage#1%
+ {\clip
+ [\c!width=\overlaywidth,\c!height=\overlayheight]
+ {\overlayimage{#1}}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/pack-com.mkxl b/tex/context/base/mkiv/pack-com.mkxl
new file mode 100644
index 000000000..5b7a16359
--- /dev/null
+++ b/tex/context/base/mkiv/pack-com.mkxl
@@ -0,0 +1,949 @@
+%D \module
+%D [ file=pack-com, % used to be in core-mis,
+%D version=20120111,
+%D title=\CONTEXT\ Packing Macros,
+%D subtitle=Combinations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Combinations}
+
+\unprotect
+
+% \startfloatcombination will be redone ... we can decouple the floatcontent
+% and caption and pass them to combinations so that we get better fit when the
+% caption is wider than the float, testcase:
+%
+% \startfloatcombination [2*2]
+% \placefigure[local]{alpha}{\externalfigure[cow.pdf][width=1cm]}%
+% \placefigure[local]{beta} {\externalfigure[cow.pdf][width=2cm]}%
+% \placefigure[local]{gamma}{\externalfigure[cow.pdf][width=3cm]}
+% \placefigure[local]{delta}{\externalfigure[cow.pdf][width=4cm]}
+% \stopfloatcombination
+
+%D We could of course map combinations onto one of the table mechanisms but as it
+%D has served us well for ages we keep this one. The code has been cleaned up a bit
+%D and mkiv'd.
+%D
+%D Okay ... I might luafy this one eventually.
+
+% \startcombination {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] \combination {alpha} {a} \combination{beta} {b} \stopcombination
+
+%D We do support some structure but the order matters and currently it's only window
+%D dressing:
+
+%D \starttyping
+%D \let\startcontent\bgroup
+%D \let\stopcontent \egroup
+%D \let\startcaption\bgroup
+%D \let\stopcaption \egroup
+%D \stoptyping
+%D
+%D Of course we should have started with more structure as it would simply the code.
+%D
+%D \starttyping
+%D \startcombination
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D Some cow.
+%D \stopcaption
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D The same cow.
+%D \stopcaption
+%D \stopcombination
+%D \stoptyping
+
+\ifdefined\dotagcombination \else \let\dotagcombination\relax \fi
+
+\newsystemmode{combination}
+
+\appendtoks
+ \globalresetsystemmode{combination}%
+\to \everyinsidefloat
+
+\newcount\c_pack_combinations_nesting % local
+
+\newcount\c_pack_combinations_x % global
+\newcount\c_pack_combinations_y % global
+\newcount\c_pack_combinations_max % global
+
+\newdimen\d_pack_combinations_ht % global
+
+\newbox \b_pack_combinations_captions % global % can go
+\newbox \b_pack_combinations_temp % global % can go
+\newbox \b_pack_combinations_content % local
+\newbox \b_pack_combinations_caption % local
+
+\installcorenamespace{combination}
+
+\installcommandhandler \??combination {combination} \??combination
+
+\initializeboxstack{\??combination captions}
+\initializeboxstack{\??combination temp}
+
+\newcount\c_pack_combinations_x_saved
+\newcount\c_pack_combinations_y_saved
+\newcount\c_pack_combinations_max_saved
+
+\newdimen\d_pack_combinations_ht_saved
+
+\newbox \b_pack_combinations_captions_saved
+\newbox \b_pack_combinations_temp_saved
+\newbox \b_pack_combinations_content_saved
+\newbox \b_pack_combinations_caption_saved
+
+\setfalse\c_strc_constructions_define_commands
+
+\def\pack_combinations_push
+ {\advance\c_pack_combinations_nesting\plusone
+ \ifnum\c_pack_combinations_nesting>\plusone
+ \c_pack_combinations_x_saved \c_pack_combinations_x
+ \c_pack_combinations_y_saved \c_pack_combinations_y
+ \c_pack_combinations_max_saved\c_pack_combinations_max
+ \d_pack_combinations_ht_saved \d_pack_combinations_ht
+ \setbox\b_pack_combinations_captions_saved\box\b_pack_combinations_captions
+ \setbox\b_pack_combinations_temp_saved \box\b_pack_combinations_temp
+ \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content
+ \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption
+ \else
+ \globalsetsystemmode{combination}% why global
+ \fi}
+
+\def\pack_combinations_pop
+ {\ifnum\c_pack_combinations_nesting>\plusone
+ \global\c_pack_combinations_x \c_pack_combinations_x_saved
+ \global\c_pack_combinations_y \c_pack_combinations_y_saved
+ \global\c_pack_combinations_max\c_pack_combinations_max_saved
+ \global\d_pack_combinations_ht \d_pack_combinations_ht_saved
+ \global\setbox\b_pack_combinations_captions\box\b_pack_combinations_captions_saved
+ \global\setbox\b_pack_combinations_temp \box\b_pack_combinations_temp_saved
+ \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved
+ \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved
+ \else
+ \globalresetsystemmode{combination}% why global
+ \fi
+ \advance\c_pack_combinations_nesting\minusone}
+
+\definelabel
+ [\v!combination] % handy for configuring
+ [\c!numberconversion=\v!character,
+ \c!text=]
+
+\settrue\c_strc_constructions_define_commands
+
+\setupcombination
+ [\c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!distance=\emwidth,
+ \c!location=\v!bottom, % can be something {top,left}
+ \c!before=\blank,
+ \c!after=,
+ \c!inbetween={\blank[\v!medium]},
+ %\c!style=,
+ %\c!color=,
+ \c!nx=2, % new
+ \c!ny=1, % new
+ \c!align=\v!middle]
+
+\let\setupcombinations\setupcombination % for the moment (we might distinguish)
+
+\installcorenamespace{combinationlocation}
+\installcorenamespace{combinationalternative}
+
+\appendtoks
+ \setfalse\c_strc_constructions_define_commands
+ \normalexpanded
+ {\definelabel
+ [\v!combination:\currentcombination]%
+ [\v!combination\ifx\currentcombinationparent\empty\else:\currentcombinationparent\fi]}%
+ [\s!counter=\currentcombination,\c!levels=1]%
+ \settrue\c_strc_constructions_define_commands
+\to \everydefinecombination
+
+\setvalue{\??combinationlocation\v!left }{\let\m_pack_combinations_leftfiller\relax}
+\setvalue{\??combinationlocation\v!right }{\let\m_pack_combinations_rightfiller\relax}
+\setvalue{\??combinationlocation\v!top }{\let\m_pack_combinations_valigner\depthonlybox}
+\setvalue{\??combinationlocation\v!middle}{\let\m_pack_combinations_valigner\halfwaybox}
+
+\def\pack_combinations_location_reset
+ {\let\m_pack_combinations_rightfiller\hfil
+ \let\m_pack_combinations_leftfiller \hfil
+ \let\m_pack_combinations_valigner \firstofoneargument}
+
+\pack_combinations_location_reset
+
+\def\pack_combinations_location_step#1%
+ {\csname\??combinationlocation#1\endcsname}
+
+% formally ok:
+%
+% \protected\def\stopcombination
+% {\egroup
+% \egroup}
+%
+% more robust:
+%
+% \protected\def\stopcombination
+% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
+% \egroup
+% \egroup}
+%
+% even better:
+%
+% \protected\def\stopcombination
+% {\bgroup
+% \scratchtoks{{}}%
+% \dorecurse\c_pack_combinations_y
+% {\toksapp{{}{}}}%
+% \expandafter\egroup\the\scratchtoks
+% \egroup
+% \dostoptagged
+% \egroup}
+%
+% faster
+
+\protected\def\pack_common_content_start{\bgroup\ignorespaces}
+\protected\def\pack_common_content_stop {\removeunwantedspaces\egroup}
+\protected\def\pack_common_caption_start{\bgroup\ignorespaces}
+\protected\def\pack_common_caption_stop {\removeunwantedspaces\egroup}
+
+\newtoks\everycombination
+
+\protected\def\stopcombination
+ {\bgroup\normalexpanded{\egroup{}\ntimes{{}{}}\c_pack_combinations_y}% brr
+ \dostoptagged
+ \egroup
+ \pack_combinations_pop
+ \egroup}
+
+\permanent\tolerant\protected\def\startcombination[#1]#*[#2]% can be simplified
+ {\bgroup % so we can grab a group
+ \pack_combinations_push
+ \edef\currentcombination{#1}%
+ \edef\currentcombinationspec{#2}%
+ \ifx\currentcombinationspec\empty
+ \ifcondition\validassignment{#1}%
+ \let\currentcombination\empty
+ \setupcurrentcombination[#1]%
+ \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}%
+ \else
+ \doifelseinstring{*}\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\doifelsenumber\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}%
+ \fi
+ \else
+ \ifcondition\validassignment{#2}%
+ \setupcurrentcombination[#2]%
+ \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}%
+ \else
+ \edef\currentcombinationspec{\currentcombinationspec*\plusone*}%
+ \fi
+ \fi
+ %
+ \forgetall
+ %
+ \the\everycombination
+ %
+ \let\startcontent\pack_common_content_start
+ \let\stopcontent \pack_common_content_stop
+ \let\startcaption\pack_common_caption_start
+ \let\stopcaption \pack_common_caption_stop
+ %
+ \edef\p_height {\combinationparameter\c!height}%
+ \edef\p_width {\combinationparameter\c!width}%
+ \edef\p_location{\combinationparameter\c!location}%
+ \edef\p_distance{\combinationparameter\c!distance}%
+ %
+ \pack_combinations_location_reset
+ \rawprocesscommacommand[\p_location]\pack_combinations_location_step
+ %
+ \dostarttaggedchained\t!combination\currentcombination\??combination
+ \vbox \ifx\p_height\v!fit\else to \p_height \fi \bgroup
+ \let\combination\empty % permits \combination{}{} handy for cld
+ \normalexpanded{\pack_combinations_start_indeed[\currentcombinationspec]}}
+
+\let\pack_combinations_check_x_y\relax
+
+\protected\def\pack_combinations_start_indeed[#1*#2*#3]%
+ {\global\c_pack_combinations_x#1\relax
+ \global\c_pack_combinations_y#2\relax
+ \setexpandedcombinationparameter\c!nx{\the\c_pack_combinations_x}% in case we access it
+ \setexpandedcombinationparameter\c!ny{\the\c_pack_combinations_y}% in case we access it
+ \pack_combinations_check_x_y
+ \dotagcombination
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \global\c_pack_combinations_max\c_pack_combinations_x
+ \multiply\c_pack_combinations_y\c_pack_combinations_x
+ \tabskip\zeropoint
+ \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup % repetitive preamble
+ \aligntab
+ \m_pack_combinations_leftfiller
+ \alignmark\alignmark
+ \m_pack_combinations_rightfiller
+ \aligntab
+ \tabskip\zeropoint \s!plus 1fill % \fillskip
+ \alignmark\alignmark
+ \cr
+ \pack_combinations_pickup}
+
+%D I've first considered using a constructor directly but it's more overhead and
+%D some settings conflict with already used combination settings so instead we plug
+%D in labels. This also permits extensions later on.
+
+\appendtoks
+ \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}%
+\to \everydefinecombination
+
+\def\pack_combinations_pickup
+ {\dostarttagged\t!combinationpair\empty % better make this text
+ \dostarttagged\t!combinationcontent\empty
+ \assumelongusagecs\pack_combinations_pickup_content_indeed}
+
+\def\pack_combinations_pickup_content_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_content\hbox}
+
+\def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box
+ {\dostoptagged
+ \setbox\b_pack_combinations_content\box\nextbox
+ \dostarttagged\t!combinationcaption\empty
+ \expandnamespacemacro\??combinationalternative\p_pack_combinations_alternative\v!text}
+
+\setvalue{\??combinationalternative\v!text}%
+ {\assumelongusagecs\pack_combinations_alternative_text_indeed}
+
+\setvalue{\??combinationalternative\v!label}%
+ {\assumelongusagecs\pack_combinations_alternative_label_indeed}
+
+\def\pack_combinations_alternative_text_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+ \afterassignment\pack_combinations_caption_first
+ \let\nexttoken=}
+
+\def\pack_combinations_alternative_label_indeed
+ {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+ \hsize\wd\b_pack_combinations_content
+ \usealignparameter\combinationparameter
+ \usecombinationstyleandcolor\c!style\c!color
+ \begstrut
+ \normalexpanded{\strc_labels_command[\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi]}%
+ \endstrut
+ \egroup}
+
+\appendtoks
+ \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}%
+ \ifx\p_pack_combinations_alternative\v!label
+ \edef\p_continue{\combinationparameter\c!continue}%
+ \ifx\p_continue\v!yes \else
+ \normalexpanded{\strc_labels_reset{\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi}{1}}%
+ \fi
+ \fi
+\to \everycombination
+
+\def\pack_combinations_pickup_caption
+ {\dostoptagged
+ \dostoptagged
+ \setbox\b_pack_combinations_caption\box\nextbox
+ \pack_combinations_pickup_package_pair}
+
+\def\pack_combinations_caption_first
+ {\futurelet\nexttoken\pack_combinations_caption_second}
+
+\def\pack_combinations_caption_second
+ {\ifx\nexttoken\egroup
+ % the caption is empty
+ \orelse\ifx\nexttoken\stopcaption
+ % the caption is empty (new per 2014-05-24)
+ \else
+ % todo: \p_pack_combinations_alternative\v!none: no style, strut etc
+ \hsize\wd\b_pack_combinations_content
+ \usealignparameter\combinationparameter
+ \usecombinationstyleandcolor\c!style\c!color
+ \bgroup
+ \aftergroup\endstrut
+ \aftergroup\egroup
+ \begstrut
+ \fi}
+
+\def\pack_combinations_pickup_package_pair % we need to store the caption row
+ {\vbox
+ {\forgetall
+ \m_pack_combinations_valigner{\box\b_pack_combinations_content}%
+ % we need to save the caption for a next alignment line
+ \pack_combinations_save_caption}%
+ \ifnum\c_pack_combinations_y>\plusone
+ \global\advance\c_pack_combinations_y\minusone
+ \global\advance\c_pack_combinations_x\minusone
+ \ifcase\c_pack_combinations_x
+ \doubleexpandafter\pack_combinations_pickup_package_pair_a
+ \else
+ \doubleexpandafter\pack_combinations_pickup_package_pair_b
+ \fi
+ \else
+ \singleexpandafter\pack_combinations_pickup_package_pair_c
+ \fi}
+
+\def\pack_combinations_pickup_package_pair_a
+ {\cr
+ \pack_combinations_flush_captions
+ \noalign
+ {\forgetall
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \nointerlineskip
+ \combinationparameter\c!after
+ \combinationparameter\c!before
+ \vss
+ \nointerlineskip}%
+ \global\c_pack_combinations_x\c_pack_combinations_max
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup_package_pair_b
+ {\aligntab
+ \aligntab
+ \aligntab
+ \kern\p_distance
+ \aligntab
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup_package_pair_c
+ {\cr
+ \pack_combinations_flush_captions
+ \egroup}
+
+\installcorenamespace{combinationcaption}
+
+\def\pack_combinations_save_caption
+ {\ifdim\htdp\b_pack_combinations_caption>\d_pack_combinations_ht
+ \global\d_pack_combinations_ht\htdp\b_pack_combinations_caption
+ \fi
+ \savebox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}{\box\b_pack_combinations_caption}}
+
+\def\pack_combinations_flush_captions
+ {\noalign
+ {\ifdim\d_pack_combinations_ht>\zeropoint
+ \nointerlineskip % indeed
+ \combinationparameter\c!inbetween
+ \global\c_pack_combinations_x\c_pack_combinations_max
+ \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes
+ \else
+ \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop
+ \fi}%
+ \pack_combinations_flush_captions_indeed
+ \crcr}
+
+\def\pack_combinations_flush_captions_yes
+ {\vpack to \d_pack_combinations_ht\bgroup
+ \foundbox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}%
+ \vss
+ \egroup
+ \global\advance\c_pack_combinations_x\minusone
+ \ifnum\c_pack_combinations_x>\zerocount % \c_pack_combinations_max
+ \expandafter\pack_combinations_flush_captions_yes_followup
+ \else
+ \global\d_pack_combinations_ht\zeropoint
+ \initializeboxstack{\??combinationcaption:\number-\c_pack_combinations_nesting}%
+ \fi}
+
+\let\pack_combinations_flush_captions_nop\donothing
+
+\def\pack_combinations_flush_captions_yes_followup
+ {\aligntab
+ \aligntab
+ \aligntab
+ \aligntab
+ \pack_combinations_flush_captions_indeed}
+
+%D \macros
+%D {startfloatcombination}
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \placefigure
+%D [left,none]
+%D {}
+%D {\startfloatcombination[2*2]
+%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]}
+%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]}
+%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]}
+%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]}
+%D \stopfloatcombination}
+%D
+%D \input tufte
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\protected\def\pack_combinations_float_hack_a#1%
+ {\strc_floats_build_box_separate_split{#1}%
+ \box\b_strc_floats_separate_content}
+
+\protected\def\pack_combinations_float_hack_b#1%
+ {\box\b_strc_floats_separate_caption}
+
+\permanent\tolerant\protected\def\startfloatcombination[#1]#*[#2]%
+ {\ifinsidefloat\else\dontleavehmode\fi % tricky, floatcombinations fail to align well otherwise
+ \vbox\bgroup
+ \strc_floats_build_box_separate_set
+ %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
+ \postcenterfloatmethod\zerocount
+ \forcelocalfloats
+ \protected\def\stopfloatcombination{\pack_combinations_stop_float{#1}}}
+
+\let\stopfloatcombination\relax
+
+\def\pack_combinations_float_check_x_y
+ {\ifnum\numexpr\c_pack_combinations_x*\c_pack_combinations_y\relax<\noflocalfloats\relax
+ \global\c_pack_combinations_x\noflocalfloats
+ \global\c_pack_combinations_y\plusone
+ \fi
+ \let\pack_combinations_check_x_y\relax}%
+
+\def\pack_combinations_stop_float#1%
+ {\scratchtoks\emptytoks
+ \dorecurse\noflocalfloats
+ {\appendetoks
+ {\pack_combinations_float_hack_a{\recurselevel}}%
+ {\pack_combinations_float_hack_b{\recurselevel}}%
+ \to\scratchtoks}% brrr
+ \let\pack_combinations_check_x_y\pack_combinations_float_check_x_y
+ \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination
+ \resetlocalfloats
+ \egroup}
+
+%D \macros
+%D {definepairedbox, setuppairedbox, placepairedbox}
+%D
+%D Paired boxes, formally called legends, but from now on a legend is just an
+%D instance, are primarily meant for typesetting some text alongside an
+%D illustration. Although there is quite some variation possible, the functionality
+%D is kept simple, if only because in most cases such pairs are typeset sober.
+%D
+%D The location specification accepts a pair, where the first keyword specifies the
+%D arrangement, and the second one the alignment. The first key of the location pair
+%D is one of \type {left}, \type {right}, \type {top} or \type {bottom}, while the
+%D second key can also be \type {middle}.
+%D
+%D The first box is just collected in an horizontal box, but the second one is a
+%D vertical box that gets passed the bodyfont and alignment settings.
+%D
+%D In many cases the table builders can be used instead, but as this mechanism is a
+%D traditional \CONTEXT\ one we keep it around.
+
+%D \macros
+%D {setuplegend, placelegend}
+%D
+%D It makes sense to typeset a legend to a figure in \TEX\ and not in a drawing
+%D package. The macro \type {\placelegend} combines a figure (or something else) and
+%D its legend. This command is just a paired box.
+%D
+%D The legend is placed according to \type {location}, being \type {bottom} or \type
+%D {right}. The macro macro is used as follows.
+%D
+%D \starttyping
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulate[|l|l|l|l|]
+%D \NC 1 \NC head \NC 3 \NC tail \NC \NR
+%D \NC 2 \NC legs \NC \NC \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {head \par legs \par tail}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2,width=.8\hsize]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \def\MytTestTwo#1#2%
+%D {\placefigure
+%D {whow}
+%D {\placelegend[location={#1,#2}]
+%D {\externalfigure[cow]}
+%D {\starttabulate
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate}}}
+%D
+%D \def\MytTestOne#1{\processcommalist[left,right,top,bottom]{\MytTestTwo{#1}}}
+%D
+%D \processcommalist[left,right,top,bottom,middle]\MytTestOne
+%D \stoptyping
+%D
+%D More structure is also possible (the order matters!):
+%D
+%D \starttyping
+%D \startplacefigure[title=whow]
+%D \startplacelegend[location={bottom,middle},color=red]
+%D \startcontent
+%D \externalfigure[cow]
+%D \stopcontent
+%D \startcaption
+%D \starttabulate[|l|l|]
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulate
+%D \stopcaption
+%D \stopplacelegend
+%D \stopplacefigure
+%D \stoptyping
+
+% todo: natural size
+
+\newsystemmode{pairedbox}
+
+\appendtoks
+ \globalresetsystemmode{pairedbox}%
+\to \everyinsidefloat
+
+\installcorenamespace {pairedbox}
+
+\installcommandhandler \??pairedbox {pairedbox} \??pairedbox
+
+\setuppairedbox
+ [\c!n=1,
+ \c!distance=\bodyfontsize,
+ %\c!before=,
+ %\c!after=,
+ %\c!color=,
+ %\c!style=,
+ \c!inbetween={\blank[\v!medium]},
+ \c!width=\hsize,
+ \c!height=\vsize,
+ \c!maxwidth=\textwidth, % \makeupwidth,
+ \c!maxheight=\textheight, % \makeupheight,
+ %\c!bodyfont=,
+ %\c!align=,
+ \c!location=\v!bottom]
+
+% watch the hsize/vsize tricks
+
+\newbox \b_pack_pairedboxes_first
+\newbox \b_pack_pairedboxes_second
+\newdimen\s_pack_pairedboxes_size
+
+\appendtoks
+ \setuevalue{\e!setup\currentpairedbox\e!endsetup}{\setuppairedbox [\currentpairedbox]}%
+ \setuevalue{\e!place\currentpairedbox }{\placepairedbox [\currentpairedbox]}% one argument is mandate anyway
+ \setuevalue{\e!start\e!place\currentpairedbox }{\startplacepairedbox[\currentpairedbox]}% one argument is mandate anyway
+ \setuevalue{\e!stop\e!place \currentpairedbox }{\stopplacepairedbox }%
+\to \everydefinepairedbox
+
+\permanent\tolerant\protected\def\startplacepairedbox[#1]#*[#2]%
+ {\bgroup
+ \edef\currentpairedbox{#1}%
+ \setupcurrentpairedbox[#2]%
+ \pairedboxparameter\c!before
+ \bgroup
+ \edef\p_location{\pairedboxparameter\c!location}%
+ \edef\p_n {\pairedboxparameter\c!n}%
+ %
+ \let\startcontent\pack_common_content_start
+ \let\stopcontent \pack_common_content_stop
+ \let\startcaption\pack_common_caption_start
+ \let\stopcaption \pack_common_caption_stop
+ %
+ \globalsetsystemmode{pairedbox}%
+ \pack_pairedboxes_before
+ \assumelongusagecs\pack_pairedboxes_first_pickup}
+
+\permanent\protected\def\stopplacepairedbox{} % we just pick up two boxes
+
+\let\placepairedbox\startplacepairedbox % we just pick up two boxes
+
+\def\pack_pairedboxes_first_pickup
+ {\dowithnextboxcs\pack_pairedboxes_first\hbox
+ \bgroup
+ \let\next=}
+
+\def\pack_pairedboxes_first
+ {\pack_pairedboxes_between
+ \assumelongusagecs\pack_pairedboxes_second_pickup}
+
+\def\pack_pairedboxes_second_pickup
+ {\dowithnextboxcs\pack_pairedboxes_second\vbox
+ \bgroup
+ \pack_pairedboxes_inside_second
+ \let\next=}
+
+\def\pack_pairedboxes_second
+ {\pack_pairedboxes_after
+ \egroup
+ \pairedboxparameter\c!after
+ \egroup}
+
+\newconditional\c_pack_pairedboxes_horizontal \settrue\c_pack_pairedboxes_horizontal
+
+\installcorenamespace{pairedboxnature}
+\installcorenamespace{pairedboxalign}
+
+\let\pack_pairedboxes_fill_top \relax
+\let\pack_pairedboxes_fill_bottom\relax
+
+\setvalue{\??pairedboxnature\v!left}%
+ {\settrue\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_left}
+
+\setvalue{\??pairedboxnature\v!right}%
+ {\settrue\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_right}
+
+\setvalue{\??pairedboxnature\v!top}%
+ {\setfalse\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_fill_top\relax
+ \let\pack_pairedboxes_fill_bottom\vss
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_top}
+
+\setvalue{\??pairedboxnature\v!bottom}%
+ {\setfalse\c_pack_pairedboxes_horizontal
+ \let\pack_pairedboxes_fill_top\vss
+ \let\pack_pairedboxes_fill_bottom\relax
+ \let\pack_pairedboxes_flush\pack_pairedboxes_flush_bottom}
+
+\def\pack_pairedboxes_flush_left
+ {\box\b_pack_pairedboxes_second
+ \kern\pairedboxparameter\c!distance
+ \box\b_pack_pairedboxes_first}
+
+\def\pack_pairedboxes_flush_right
+ {\box\b_pack_pairedboxes_first
+ \kern\pairedboxparameter\c!distance
+ \box\b_pack_pairedboxes_second}
+
+\def\pack_pairedboxes_flush_top
+ {\box\b_pack_pairedboxes_second
+ \endgraf
+ \nointerlineskip
+ \pairedboxparameter\c!inbetween
+ \box\b_pack_pairedboxes_first}
+
+\def\pack_pairedboxes_flush_bottom
+ {\box\b_pack_pairedboxes_first
+ \endgraf
+ \nointerlineskip
+ \pairedboxparameter\c!inbetween
+ \box\b_pack_pairedboxes_second}
+
+\setvalue{\??pairedboxalign\v!left}% 0
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\hss
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign\v!right}% 1
+ {\let\pack_pairedboxes_align_l\hss
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign\v!high}% 2
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\relax
+ \let\pack_pairedboxes_align_b\vss}
+
+\setvalue{\??pairedboxalign\v!low}% 3
+ {\let\pack_pairedboxes_align_l\relax
+ \let\pack_pairedboxes_align_r\relax
+ \let\pack_pairedboxes_align_t\vss
+ \let\pack_pairedboxes_align_b\relax}
+
+\setvalue{\??pairedboxalign\v!middle}% 4
+ {\let\pack_pairedboxes_align_l\hss
+ \let\pack_pairedboxes_align_r\hss
+ \let\pack_pairedboxes_align_t\vss
+ \let\pack_pairedboxes_align_b\vss}
+
+\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }}
+\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}}
+
+\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}}
+\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}}
+
+\def\pack_pairedboxes_before
+ {\ifx\p_location\empty
+ \csname\??pairedboxnature\v!left \endcsname
+ \csname\??pairedboxalign \v!middle\endcsname
+ \else
+ \getfromcommacommand[\p_location][1]%
+ \csname\??pairedboxnature
+ \ifcsname\??pairedboxnature\commalistelement\endcsname\commalistelement\else\v!left\fi
+ \endcsname
+ \getfromcommacommand[\p_location][2]%
+ \csname\??pairedboxalign
+ \ifcsname\??pairedboxalign\commalistelement\endcsname\commalistelement\else\v!middle\fi
+ \endcsname
+ \fi}
+
+\def\pack_pairedboxes_between
+ {\usebodyfontparameter\pairedboxparameter
+ \setbox\b_pack_pairedboxes_first\box\nextbox
+ \ifconditional\c_pack_pairedboxes_horizontal
+ \pack_pairedboxes_between_horizontal
+ \else
+ \pack_pairedboxes_between_vertical
+ \fi
+ \ifnum\p_n>\plusone
+ \setrigidcolumnhsize\hsize{\pairedboxparameter\c!distance}\p_n
+ \fi}
+
+\def\pack_pairedboxes_between_horizontal
+ {\scratchdistance\pairedboxparameter\c!distance
+ \scratchwidth\pairedboxparameter\c!maxwidth\relax
+ \setlocalhsize
+ \hsize\dimexpr\availablehsize-\wd\b_pack_pairedboxes_first-\scratchdistance\relax
+ \hsize\pairedboxparameter\c!width\relax % can be \hsize
+ \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\scratchdistance\relax
+ \ifdim\dimexpr\hsize+\scratchdimen\relax>\scratchwidth
+ \hsize\dimexpr\scratchwidth-\scratchdimen\relax
+ \fi}
+
+\def\pack_pairedboxes_between_vertical
+ {\scratchwidth\pairedboxparameter\c!maxwidth\relax
+ \hsize\wd\b_pack_pairedboxes_first
+ \hsize\pairedboxparameter\c!width\relax % can be \hsize
+ \ifdim\hsize>\scratchwidth\relax
+ \hsize\scratchwidth
+ \fi}
+
+\def\pack_pairedboxes_after
+ {\setbox\b_pack_pairedboxes_second\vpack
+ {\ifnum\p_n>\plusone
+ \rigidcolumnbalance\nextbox
+ \else
+ \box\nextbox
+ \fi}%
+ \ifconditional\c_pack_pairedboxes_horizontal
+ \pack_pairedboxes_pack_horizontal
+ \else
+ \pack_pairedboxes_pack_vertical
+ \fi}
+
+\def\pack_pairedboxes_pack_horizontal
+ {\dontleavehmode\hbox\bgroup
+ \forgetall
+ \s_pack_pairedboxes_size\ht
+ \ifdim\ht\b_pack_pairedboxes_first>\ht\b_pack_pairedboxes_second
+ \b_pack_pairedboxes_first
+ \else
+ \b_pack_pairedboxes_second
+ \fi
+ \vsize\s_pack_pairedboxes_size
+ \ifdim\s_pack_pairedboxes_size<\pairedboxparameter\c!height\relax % can be \vsize
+ \s_pack_pairedboxes_size\pairedboxparameter\c!height
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax
+ \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight
+ \fi
+ \pack_pairedbox_valign\b_pack_pairedboxes_first
+ \pack_pairedbox_valign\b_pack_pairedboxes_second
+ \pack_pairedboxes_flush
+ \egroup}
+
+\def\pack_pairedboxes_pack_vertical
+ {\dontleavehmode\vpack\bgroup
+ \forgetall
+ \s_pack_pairedboxes_size\wd
+ \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second
+ \b_pack_pairedboxes_first
+ \else
+ \b_pack_pairedboxes_second
+ \fi
+ \pack_pairedbox_halign\b_pack_pairedboxes_first
+ \pack_pairedbox_halign\b_pack_pairedboxes_second
+ \s_pack_pairedboxes_size\ht\b_pack_pairedboxes_second
+ \vsize\s_pack_pairedboxes_size
+ \ifdim\ht\b_pack_pairedboxes_second<\pairedboxparameter\c!height\relax % can be \vsize
+ \s_pack_pairedboxes_size\pairedboxparameter\c!height\relax % \relax needed
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax % todo: totale hoogte
+ \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed
+ \fi
+ \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second
+ \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size
+ {\pack_pairedboxes_fill_top
+ \box\b_pack_pairedboxes_second
+ \pack_pairedboxes_fill_bottom}% \kern\zeropoint
+ \fi
+ \pack_pairedboxes_flush
+ \egroup}
+
+\def\pack_pairedboxes_inside_second
+ {\forgetall
+ \setupalign[\pairedboxparameter\c!align]%
+ \usepairedboxstyleandcolor\c!style\c!color
+ \tolerantTABLEbreaktrue % hm.
+ \blank[\v!disable]% use fast one
+ \everypar{\begstrut}} % also flushers here (see bTABLE)
+
+\definepairedbox[\v!legend]
+
+\permanent\protected\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox}
+\permanent\protected\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox}
+
+\def\pack_topofeachother_one{\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox}
+\def\pack_sidebyside_one {\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox}
+
+\def\pack_topofeachother_two{\setbox\scratchboxtwo\box\nextbox
+ \halign{\hss\alignmark\alignmark\hss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}%
+ \egroup\egroup}
+\def\pack_sidebyside_two {\setbox\scratchboxtwo\box\nextbox
+ \valign{\vss\alignmark\alignmark\vss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}%
+ \egroup\egroup}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/pack-lyr.mkxl b/tex/context/base/mkiv/pack-lyr.mkxl
index 419c9f279..366eeff75 100644
--- a/tex/context/base/mkiv/pack-lyr.mkxl
+++ b/tex/context/base/mkiv/pack-lyr.mkxl
@@ -32,11 +32,10 @@
\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi
-\unexpanded\def\defineoverlay
- {\dotripleempty\pack_framed_define_overlay}
+\pushoverloadmode
-\def\pack_framed_define_overlay[#1][#2][#3]% overlay [layer] content
- {\ifthirdargument
+\permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#2]#*[#3]% overlay [layer] content
+ {\ifnum\lastarguments=\plusthree
%\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}%
\else
@@ -44,6 +43,8 @@
\fi
\processcommalist[#1]\pack_framed_define_overlay_indeed}
+\popoverloadmode
+
%D We use the command handler code. The previous, more direct parameter handling was
%D 25\% faster when no parameters were passed when adding content to a layer.
%D However, when we pass for instance a preset, the new methos is some 10\% faster
@@ -130,7 +131,7 @@
\newconditional\c_pack_layers_trace
\newcount \c_pack_layers_current_data
-\newbox\b_layers
+\newbox\b_layers \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode
\newdimen\d_pack_layers_x_size
\newdimen\d_pack_layers_y_size
@@ -178,7 +179,7 @@
\global\setbox\lastnamedcs\emptybox
\fi}
-\def\resetlayer[#1]%
+\permanent\protected\def\resetlayer[#1]%
{\pack_layers_reset_box{#1}%
\pack_layers_reset_box{\v!left #1}%
\pack_layers_reset_box{\v!right#1}%
@@ -195,37 +196,33 @@
%D \setlayer [identifier] [optional parameters] {data}
%D \stoptyping
-\def\setcurrentlayerdimensions
- {\dodoubleempty\pack_layers_set_current_dimensions}
-
-\def\pack_layers_set_current_dimensions[#1][#2]% name left|right
+\permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right
{\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
\edef\currentlayerheight{\thelayerheight{#2#1}}}
-\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
-\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
+\permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
+\permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
-\unexpanded\def\setlayer
- {\dotripleempty\pack_layers_set}
-
-\def\pack_layers_set[#1][#2][#3]% #4 == box do \fi is ok
+\permanent\tolerant\protected\def\setlayer[#1]#*[#2]#*[#3]% #4 == box do \fi is ok
{\bgroup
+ \nofarguments\lastarguments
\checkpositionoverlays % otherwise funny regions
\edef\currentlayer{#1}%
\edef\p_pack_layers_state{\layerparameter\c!state}%
\ifx\p_pack_layers_state\v!stop
\dowithnextboxcs\egroup\hbox % no pack ?
- \orelse\ifthirdargument
- \pack_layers_set_indeed[#1][#2][#3]%
+ \orelse\ifnum\nofarguments=\plusthree
+ \edef\m_pack_layers_target{#2}%
+ \pack_layers_set_indeed{#3}%
+ \orelse\ifhastok={#2}%
+ \let\m_pack_layers_target\empty
+ \pack_layers_set_indeed{#2}%
\else
- \ifcondition\validassignment{#2}%
- \pack_layers_set_indeed[#1][][#2]%
- \else
- \pack_layers_set_indeed[#1][#2][]%
- \fi
+ \edef\m_pack_layers_target{#2}%
+ \pack_layers_set_indeed\empty
\fi}
-\def\pack_layers_set_indeed[#1][#2][#3]% #2 = links/rechts
+\def\pack_layers_set_indeed#1%
{\page_backgrounds_recalculate % brrr
\global\advance\c_pack_layers_current_data\plusone
\forgetall
@@ -235,8 +232,7 @@
\settrue\c_pack_layers_trace
\traceboxplacementtrue
\fi
- \edef\m_pack_layers_target{#2}%
- \dowithnextbox{\pack_layers_set_finish{#3}}\hbox}
+ \dowithnextbox{\pack_layers_set_finish{#1}}\hbox}
\def\pack_layers_set_finish#1%
{\ifcsname\??layerbox\currentlayer\endcsname % can move up
@@ -295,13 +291,15 @@
\doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
\edef\m_pack_layers_page{\layerparameter\c!page}}
-\unexpanded\def\definelayerpreset
- {\dodoubleargument\pack_layers_define_preset}
-
-\def\pack_layers_define_preset[#1][#2]%
- {\doifelseassignment{#2}
- {\setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}}
- {\setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}}}
+\permanent\tolerant\protected\def\definelayerpreset[#1]#*[#2]%
+ {\ifarguments
+ \or
+ \letvalue{\??layerpreset#1}\empty
+ \orelse\ifhastok={#2}%
+ \setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}%
+ \else
+ \setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}%
+ \fi}
\def\pack_layers_set_content#1%
{\layerwidth \layerparameter\c!width % global (local later)
@@ -477,7 +475,7 @@
%D \macros
%D {doifelselayerdata}
-\def\doifelselayerdata#1%
+\permanent\def\doifelselayerdata#1%
{\ifcsname\??layerbox#1\endcsname
%\ifvoid\csname\??layerbox#1\endcsname
\ifvoid\lastnamedcs
@@ -500,7 +498,7 @@
% todo: setups before flush, handy hook
-\unexpanded\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
+\permanent\protected\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
{\begingroup
\forgetall
\edef\currentlayer{#1}%
@@ -529,21 +527,7 @@
\fi
\endgroup}
-% \def\pack_layers_flush_single
-% {\startoverlay
-% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
-% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}%
-% \stopoverlay}
-%
-% \def\pack_layers_flush_double#1%
-% {\startoverlay
-% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
-% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}%
-% {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}%
-% {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}%
-% \stopoverlay}
-
-% optimized:
+% optimized
\def\pack_layers_flush_single
{\ifcsname\??layerbox\currentlayer\endcsname
@@ -606,7 +590,6 @@
\let\pack_layers_top_fill \relax
\let\pack_layers_bottom_fill\vss
-%def\pack_layers_flush_indeed#1#2%
\def\pack_layers_flush_indeed#1#2#3%
{\begingroup % already grouped
\offinterlineskip
@@ -705,9 +688,9 @@
%D This is a handy shortcut, which saves a couple of braces when we use it as
%D parameter. This name also suits better to other layering commands.
-\unexpanded\def\composedlayer#1{\flushlayer[#1]}
+\permanent\protected\def\composedlayer#1{\flushlayer[#1]}
-\unexpanded\def\tightlayer[#1]%
+\permanent\protected\def\tightlayer[#1]%
{\hpack
{\def\currentlayer{#1}% todo: left/right
\setbox\nextbox\emptybox
@@ -747,21 +730,15 @@
%D {\useMPgraphic{oeps}}
%D \stoptyping
-\unexpanded\def\setMPlayer
- {\dotripleempty\pack_layers_set_MP}
-
\def\MPlayerwidth {\hsize}
\def\MPlayerheight{\vsize}
-\def\pack_layers_set_MP[#1][#2][#3]%
+\permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[#3]%
{\edef\MPlayerwidth {\MPw{#2}}%
\edef\MPlayerheight{\MPh{#2}}%
\setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
-\unexpanded\def\getMPlayer
- {\dodoubleempty\pack_layers_get_MP}
-
-\def\pack_layers_get_MP[#1][#2]%
+\permanent\tolerant\protected\def\getMPlayer[#1]#*[#2]%
{\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument
%D Watch out, a redefinition:
@@ -778,9 +755,11 @@
[\c!width=\innermakeupwidth,
\c!height=\textheight]
-\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
+\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
+
+\overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
-\unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+\permanent\overloaded\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear
{\doifelselayerdata{OTRTEXT}
{\setbox#1\hpack to \makeupwidth
{\startoverlay
diff --git a/tex/context/base/mkiv/pack-mrl.mkxl b/tex/context/base/mkiv/pack-mrl.mkxl
index 7b09b2406..fd4153a6b 100644
--- a/tex/context/base/mkiv/pack-mrl.mkxl
+++ b/tex/context/base/mkiv/pack-mrl.mkxl
@@ -38,7 +38,7 @@
\installsimplecommandhandler \??blackrules {blackrules} \??blackrules
-\unexpanded\def\blackrule
+\permanent\protected\def\blackrule
{\hpack\bgroup
\doifelsenextoptionalcs\pack_black_rule_pickup\pack_black_rule_indeed}
@@ -98,16 +98,10 @@
%D We could of course have implemented this macro using \type {\leaders}, but this
%D would probably have taken more tokens.
-\unexpanded\def\blackrules % probably never used
+\permanent\tolerant\protected\def\blackrules[#1]% probably never used
{\hpack\bgroup
- \doifelsenextoptionalcs\pack_black_rules_pickup\pack_black_rules_indeed}
-
-\def\pack_black_rules_pickup[#1]%
- {\setupcurrentblackrules[#1]%
- \pack_black_rules_indeed}
-
-\def\pack_black_rules_indeed % no max handling here
- {\scratchwidth \directblackrulesparameter\c!width
+ \ifarguments\or\setupcurrentblackrules[#1]\fi
+ \scratchwidth \directblackrulesparameter\c!width
\scratchheight \directblackrulesparameter\c!height
\scratchdepth \directblackrulesparameter\c!depth
\scratchdistance\directblackrulesparameter\c!distance
@@ -171,7 +165,7 @@
%D \showsetup{vl}
%D \showsetup{hl}
-\unexpanded\def\pack_rule_vl_indeed#1#2#3%
+\protected\def\pack_rule_vl_indeed#1#2#3%
{\dontleavehmode
\begingroup
\setbox\scratchbox\hbox
@@ -184,10 +178,10 @@
\box\scratchbox
\endgroup}
-\def\pack_rule_vl[#1]%
+\permanent\tolerant\protected\def\vl[#1]%
{\pack_rule_vl_indeed{#1}{#1}{#1}}
-\def\pack_rule_hl[#1]%
+\permanent\tolerant\protected\def\hl[#1]%
{\dontleavehmode
\hbox
{\vrule
@@ -195,9 +189,6 @@
\s!height\linewidth
\s!depth \zeropoint}}
-\unexpanded\def\vl{\dosingleempty\pack_rule_vl}
-\unexpanded\def\hl{\dosingleempty\pack_rule_hl}
-
\let\dovlwdhtdp\pack_rule_vl_indeed % used elsewhere
%D \macros
@@ -273,7 +264,7 @@
\newconstant\c_pack_thinrules_type
-\unexpanded\def\thinrule
+\permanent\protected\def\thinrule
{\strut
\bgroup
\edef\p_height {\directthinrulesparameter\c!height}%
@@ -362,15 +353,12 @@
\strut
\carryoverpar\egroup}
-\unexpanded\def\hairline
+\permanent\protected\def\hairline % can be overloaded
{\endgraf
\thinrule
\endgraf}
-\unexpanded\def\thinrules
- {\dosingleempty\pack_thinrules}
-
-\def\pack_thinrules[#1]%
+\permanent\tolerant\protected\def\thinrules[#1]%
{\bgroup
\setupcurrentthinrules[#1]%
\scratchcounter\directthinrulesparameter\c!n\relax
@@ -533,7 +521,9 @@
\c!rulethickness=\linewidth,
\c!distance=.5\emwidth]
-\unexpanded\def\textrule
+% can be done nicer with futureexpandis
+
+\permanent\protected\def\textrule
{\dosingleempty\pack_textrule}
\def\pack_textrule
@@ -679,14 +669,14 @@
%D The grouped commands also supports bodyfont switching:
-\unexpanded\def\starttextrule#1%
+\permanent\protected\def\starttextrule#1%
{\bgroup
\def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}%
\csname\??textrulealternatives\v!top\endcsname{#1}%
\bgroup
\usebodyfontparameter\directtextrulesparameter}
-\unexpanded\def\stoptextrule
+\permanent\protected\def\stoptextrule
{\par
\egroup
\csname\??textrulealternatives\v!bottom\endcsname\empty
@@ -713,7 +703,6 @@
%D \showsetup{fillinrules}
%D \showsetup{setupfillinrules}
-
\installcorenamespace{fillinrules}
\installdirectcommandhandler \??fillinrules {fillinrules}
@@ -729,28 +718,20 @@
\c!style=,
\c!color=]
-\unexpanded\def\fillinrules
- {\dosingleempty\pack_fillinrules}
-
-\def\pack_fillinrules[#1]%
+\permanent\tolerant\protected\def\fillinrules[#1]#:#=#*#=%
{\endgraf
\begingroup
\setupcurrentfillinrules[#1]%
\let\pack_fillinrules_rule\thinrules
- \dodoublegroupempty\pack_fillinrules_indeed}
-
-\def\pack_fillinrules_indeed#1#2%
- {\directfillinrulesparameter\c!before
+ \directfillinrulesparameter\c!before
\setupcurrentthinrules
[\c!n=\directfillinrulesparameter\c!n,
\c!interlinespace=\directfillinrulesparameter\c!interlinespace,
\c!before=,
\c!after=]%
\scratchdistance\directfillinrulesparameter\c!distance\relax
- \edef\m_fillinrules_one{#1}%
- \edef\m_fillinrules_two{#2}%
\noindent
- \ifx\m_fillinrules_one\empty \else
+ \iftok{#2}\emptytoks\else
\edef\p_width{\directfillinrulesparameter\c!width}%
\ifx\p_width\v!fit
\scratchdistance\zeropoint
@@ -763,7 +744,7 @@
\bgroup
\usefillinrulesstyleandcolor\c!style\c!color
\strut
- \m_fillinrules_one
+ #2%
\hfill\directfillinrulesparameter\c!separator
\hskip\scratchdistance
\egroup
@@ -771,10 +752,10 @@
\setupwhitespace[\v!big]%
\ignorespaces
\pack_fillinrules_rule
- \ifx\m_fillinrules_two\empty \else
+ \iftok{#3}\emptytoks\else
\kern\scratchdistance
\usefillinrulesstyleandcolor\c!style\c!color
- \m_fillinrules_two
+ #3%
\strut
\fi
\endgraf
@@ -789,18 +770,12 @@
%D
%D \showsetup{fillintext}
-\unexpanded\def\fillintext
- {\dosingleempty\pack_fillintext}
-
-\def\pack_fillintext[#1]% ugly
+\permanent\tolerant\protected\def\fillintext[#1]#:#=#*#=%
{\endgraf
\begingroup
\setupcurrentfillinrules[#1]%
- \dodoublegroupempty\pack_fillintext_indeed}
-
-\def\pack_fillintext_indeed#1#2%
- {\def\pack_fillinrules_rule{\unhbox\nextbox\unskip}%
- \dowithnextbox{\pack_fillinrules_indeed{#1}{\hfill#2}}%
+ \def\pack_fillinrules_rule{\unhbox\nextbox\unskip}%
+ \dowithnextbox{\pack_fillinrules_indeed{#2}{\hfill#3}}%
\hbox\bgroup\let\par\egroup\ignorespaces}
%D \macros
@@ -842,10 +817,10 @@
\c!before=\blank,
\c!after=\blank]
-\unexpanded\def\pack_fillinline_before#1%
+\protected\def\pack_fillinline_before#1%
{}
-\unexpanded\def\pack_fillinline_after#1%
+\protected\def\pack_fillinline_after#1%
{\begingroup
\setupcurrentfillinlines[#1]%
\ifhmode\unskip\hfill\fi
@@ -865,10 +840,7 @@
\frozen\parfillskip\zeropoint\relax
\endgroup}
-\unexpanded\def\fillinline
- {\dosingleempty\pack_fillinline}
-
-\def\pack_fillinline[#1]%
+\permanent\tolerant\protected\def\fillinline[#1]%
{\registerparwrapper
{fillinline}%
{\pack_fillinline_before{#1}}%
diff --git a/tex/context/base/mkiv/pack-ori.mkxl b/tex/context/base/mkiv/pack-ori.mkxl
index 2091adea4..4365db3ac 100644
--- a/tex/context/base/mkiv/pack-ori.mkxl
+++ b/tex/context/base/mkiv/pack-ori.mkxl
@@ -54,7 +54,7 @@
%D There will be some more helpers here.
-\def\theorientation#1%
+\permanent\def\theorientation#1%
{\numexpr
\ifcsname\??orientations#1\endcsname
\lastnamedcs
@@ -63,7 +63,7 @@
\fi
\relax}
-\def\autoorientation#1%
+\permanent\def\autoorientation#1%
{\numexpr
\ifcsname\??orientations#1\endcsname
\lastnamedcs
@@ -85,7 +85,7 @@
%{\localcontrolled{\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}}% % a bit slower
\csname\??orientations#1\endcsname}
-\unexpanded\def\doifelseorientation#1%
+\permanent\protected\def\doifelseorientation#1%
{\ifcsname\??orientations#1\endcsname
\expandafter\firstoftwoarguments
\else
diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv
index 393668c60..e06949ed8 100644
--- a/tex/context/base/mkiv/pack-rul.mkiv
+++ b/tex/context/base/mkiv/pack-rul.mkiv
@@ -2693,7 +2693,7 @@
% \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used
\letframedtextparameter\c!strut\v!no
\inheritedframedtextframed\bgroup
- \let\\=\endgraf
+ \let\\\endgraf
\edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}%
\ifx\p_framed_text_depthcorrection\v!on
\pack_framed_text_start_depth_correction
@@ -2814,7 +2814,7 @@
\letframedtextparameter\c!strut\v!no
\inheritedframedtextframed\bgroup
\blank[\v!disable]%
- \let\\=\endgraf
+ \let\\\endgraf
\useframedtextstyleandcolor\c!style\c!color
\vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
\framedtextparameter\c!inner
@@ -3007,8 +3007,6 @@
%D A Goodie:
-\def\v!unframed{unframed}
-
\defineframed
[\v!unframed]
[\c!frame=\v!off,
diff --git a/tex/context/base/mkiv/pack-rul.mkxl b/tex/context/base/mkiv/pack-rul.mkxl
index 69050d1fa..07aae0c92 100644
--- a/tex/context/base/mkiv/pack-rul.mkxl
+++ b/tex/context/base/mkiv/pack-rul.mkxl
@@ -37,10 +37,7 @@
\newdimen\linewidth
-\unexpanded\def\setuplinewidth
- {\dosingleargument\pack_framed_setup_line_width}
-
-\def\pack_framed_setup_line_width[#1]%
+\permanent\tolerant\protected\def\setuplinewidth[#1]%
{\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
%D The parameter handler:
@@ -61,9 +58,9 @@
\let\pack_framed_setupcurrentframed \setupcurrentframed
\def\pack_framed_initialize
- {\let\framedparameter \pack_framed_framedparameter
- \let\framedparameterhash\pack_framed_framedparameterhash
- \let\setupcurrentframed \pack_framed_setupcurrentframed
+ {\enforced\let\framedparameter \pack_framed_framedparameter
+ \enforced\let\framedparameterhash\pack_framed_framedparameterhash
+ \enforced\let\setupcurrentframed \pack_framed_setupcurrentframed
\inframedtrue}
%D A helper:
@@ -72,7 +69,7 @@
%D Inheritance:
-\def\installinheritedframed#1%
+\permanent\protected\def\installinheritedframed#1%
{\normalexpanded{\doinstallinheritedframed
\expandafter\noexpand\csname current#1\endcsname
\expandafter\noexpand\csname #1parameter\endcsname
@@ -84,37 +81,36 @@
\expandafter\noexpand\csname inherited#1framed\endcsname
\expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new
-\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
- {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
- %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
- \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
- \unexpanded\def#8%
+\protected\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
+ {\enforced\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
+ \enforced\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
+ \protected\def#8%
{\bgroup
\bgroup
\inframedtrue
- \let\currentframed #1%
- \let\framedparameter #2%
- \let\framedparameterhash#3%
- \let\setupcurrentframed #7%
+ \enforced\let\currentframed #1%
+ \enforced\let\framedparameter #2%
+ \enforced\let\framedparameterhash#3%
+ \enforced\let\setupcurrentframed #7%
\pack_framed_process_indeed}%
- \unexpanded\def#9%
+ \protected\def#9%
{\bgroup
\inframedtrue
- \let\currentframed #1%
- \let\framedparameter #2%
- \let\framedparameterhash#3%
- \let\setupcurrentframed #7%
+ \enforced\let\currentframed #1%
+ \enforced\let\framedparameter #2%
+ \enforced\let\framedparameterhash#3%
+ \enforced\let\setupcurrentframed #7%
\pack_framed_process_box_indeed}}
-\unexpanded\def\installframedcommandhandler#1#2#3%
+\permanent\protected\def\installframedcommandhandler#1#2#3%
{\installcommandhandler{#1}{#2}{#3}%
\installinheritedframed{#2}}
-\unexpanded\def\installframedautocommandhandler#1#2#3%
+\permanent\protected\def\installframedautocommandhandler#1#2#3%
{\installautocommandhandler{#1}{#2}{#3}%
\installinheritedframed{#2}}
-\unexpanded\def\installsimpleframedcommandhandler#1#2#3%
+\permanent\protected\def\installsimpleframedcommandhandler#1#2#3%
{\installsimplecommandhandler{#1}{#2}{#3}%
\installinheritedframed{#2}}
@@ -192,11 +188,11 @@
\c!toffset=\zeropoint,
\c!boffset=\zeropoint]
-\unexpanded\def\definesimplifiedframed[#1]% no settings
+\permanent\protected\def\definesimplifiedframed[#1]% no settings
{\defineframed[#1][\??simplifiedframed]%
- \expandafter\let\csname#1\endcsname\undefined}
+ \letcsname#1\endcsname\undefined}
-\expandafter\let\csname\??simplifiedframed\endcsname\undefined
+\letcsname\??simplifiedframed\endcsname\undefined
%D We will communicate through module specific variables, current framed
%D parameters and some reserved dimension registers.
@@ -416,7 +412,7 @@
\let\overlaycolor \empty
\let\overlaylinecolor \empty
-\def\overlayradius{\framedparameter\c!frameradius}
+\permanent\def\overlayradius{\framedparameter\c!frameradius}
\newdimen\d_overlay_width
\newdimen\d_overlay_height
@@ -428,20 +424,20 @@
% expandable ... in a future version the space will go (in mp one can use Overlay*)
-\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables
-\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default
-\def\overlaydepth {\the\d_overlay_depth \space} % values.
-\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are)
-\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else.
-\def\overlayregion {\m_overlay_region}
+\permanent\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables
+\permanent\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default
+\permanent\def\overlaydepth {\the\d_overlay_depth \space} % values.
+\permanent\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are)
+\permanent\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else.
+\permanent\def\overlayregion {\m_overlay_region}
% public but kind of protected
-\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax}
-\def\usedoverlayheight {\dimexpr\d_overlay_height \relax}
-\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax}
-\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax}
-\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax}
+\permanent\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax}
+\permanent\def\usedoverlayheight {\dimexpr\d_overlay_height \relax}
+\permanent\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax}
+\permanent\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax}
+\permanent\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax}
%D The next register is used to initialize overlays.
@@ -462,14 +458,11 @@
\vsize\d_overlay_height
\to \everyoverlay
-\unexpanded\def\defineoverlay
- {\dodoubleargument\pack_framed_define_overlay}
-
-\def\pack_framed_define_overlay[#1][#2]%
+\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded
{\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
\processcommalist[#1]\pack_framed_define_overlay_indeed}
-\unexpanded\def\executedefinedoverlay#1#2% we can share the definitions
+\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions
{\bgroup % redundant grouping
\setlayoutcomponentattribute{\v!overlay:#1}%
\setbox\scratchbox\hbox \layoutcomponentboxattribute{\the\everyoverlay#2}%
@@ -484,7 +477,7 @@
%D \macros
%D {overlayfakebox}
-\unexpanded\def\overlayfakebox
+\permanent\protected\def\overlayfakebox
{\hpack % redundant but needs testing
{\novrule
\s!width \d_overlay_width
@@ -493,7 +486,7 @@
%D For testing we provide:
-\def\doifelseoverlay#1% only tests external overlays
+\permanent\def\doifelseoverlay#1% only tests external overlays
{\ifcsname\??overlay#1\endcsname
\expandafter\firstoftwoarguments
\else
@@ -776,62 +769,49 @@
\installcorenamespace{regularframedlevel}
-\unexpanded\def\installregularframed#1%
+\permanent\protected\def\installregularframed#1%
{\defineframed[#1]}
-\unexpanded\def\presetlocalframed[#1]%
+\permanent\protected\def\presetlocalframed[#1]%
{\defineframed[#1]}
% \presetlocalframed[\??framed]
\newcount\c_pack_framed_nesting
-\unexpanded\def\pack_framed_process_framed[#1]%
- {\bgroup
- \iffirstargument % faster
- \setupcurrentframed[#1]% here !
- \fi
- \pack_framed_process_indeed}
-
-\unexpanded\def\framed
+\permanent\tolerant\protected\def\framed[#1]%
{\bgroup
\advance\c_pack_framed_nesting\plusone
- \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
- \edef\currentframed{>\the\c_pack_framed_nesting}%
- \pack_framed_initialize
- \dosingleempty\pack_framed_process_framed}
-
-\unexpanded\def\startframed
- {\dosingleempty\pack_framed_start_framed}
-
-\def\pack_framed_start_framed[#1]%
- {\bgroup
- \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}}
-
-\def\pack_framed_start_framed_yes#1%
- {\advance\c_pack_framed_nesting\plusone
- \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
- \iffirstargument\secondargumenttrue\fi % dirty trick
+ \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
\edef\currentframed{>\the\c_pack_framed_nesting}%
\pack_framed_initialize
\bgroup
- \iffirstargument
- \secondargumenttrue % dirty trick
- \setupcurrentframed[#1]% here !
- \fi
- \pack_framed_process_indeed
- \bgroup
- \ignorespaces}
-
-\def\pack_framed_start_framed_nop#1%
- {\edef\currentframed{#1}%
- \dosingleempty\pack_framed_start_framed_nop_indeed}
+ \setupcurrentframed[#1]% here !, seldom no argument so no need to optimize
+ \pack_framed_process_indeed}
-\def\pack_framed_start_framed_nop_indeed[#1]%
- {\pack_framed_initialize
- \bgroup
- \iffirstargument
- \setupcurrentframed[#1]% here !
+\permanent\tolerant\protected\def\startframed[#1]#*[#2]%
+ {\bgroup
+ \ifarguments
+ \pack_framed_initialize
+ \bgroup
+ \or
+ \ifhastok={#1}%
+ \advance\c_pack_framed_nesting\plusone
+ \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \bgroup
+ \setupcurrentframed[#1]% here !
+ \else
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \bgroup
+ \fi
+ \else
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \bgroup
+ \setupcurrentframed[#2]% here !
\fi
\pack_framed_process_indeed
\bgroup
@@ -839,14 +819,14 @@
% till here
-\unexpanded\def\stopframed
+\permanent\protected\def\stopframed
{\removeunwantedspaces
\egroup}
-\unexpanded\def\normalframedwithsettings[#1]%
+\protected\def\normalframedwithsettings[#1]%
{\bgroup
\advance\c_pack_framed_nesting\plusone
- \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
\bgroup
\edef\currentframed{>\the\c_pack_framed_nesting}%
\pack_framed_initialize
@@ -880,21 +860,23 @@
\newif\ifinframed
-%D The next one is faster on multiple backgrounds per page. No
-%D dimensions can be set, only frames and backgrounds.
+%D The next one is faster on multiple backgrounds per page. No dimensions can be
+%D set, only frames and backgrounds.
-\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
+%% \protected\def\fastlocalframed[#1]#2[#3]#4% 3-4
+
+\permanent\protected\def\fastlocalframed[#1]#*[#2]#3%
{\bgroup
\edef\currentframed{#1}%
\pack_framed_initialize
- \setbox\b_framed_normal\hbox{#4}%
+ \setbox\b_framed_normal\hbox{#3}%
\iftrialtypesetting \else
\edef\m_overlay_region{\framedparameter\c!region}%
\ifempty\m_overlay_region\else
\pack_framed_set_region
\fi
\fi
- \setupcurrentframed[#3]%
+ \setupcurrentframed[#2]%
\edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
\d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
\edef\p_framed_frame{\framedparameter\c!frame}%
@@ -928,7 +910,7 @@
%D The next macro uses a box and takes its natural width and height so these
%D can better be correct.
-\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
+\protected\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
{\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2
\edef\m_overlay_region{\framedparameter\c!region}%
\ifempty\m_overlay_region\else
@@ -961,7 +943,7 @@
\box\b_framed_normal
\egroup}
-\unexpanded\def\localbackgroundframed#1% namespace component box
+\protected\def\localbackgroundframed#1% namespace component box
{\bgroup
\edef\currentframed{#1}%
\pack_framed_initialize
@@ -988,37 +970,26 @@
% todo: protect local \framednames
-\unexpanded\def\localframed
- {\bgroup
- \dodoubleempty\pack_framed_local}
-
-\unexpanded\def\pack_framed_local[#1][#2]%
- {\bgroup
- \edef\currentframed{#1}%
- \pack_framed_initialize
- \ifsecondargument % faster
- \setupcurrentframed[#2]% here !
- \fi
- \pack_framed_process_indeed}
-
-\unexpanded\def\directlocalframed[#1]% no optional
+\permanent\tolerant\protected\def\localframed[#1]#*[#2]%
{\bgroup
\bgroup
\edef\currentframed{#1}%
\pack_framed_initialize
+ \setupcurrentframed[#2]% here !
\pack_framed_process_indeed}
-\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
+\permanent\protected\def\directlocalframed[#1]% no optional
{\bgroup
\bgroup
\edef\currentframed{#1}%
\pack_framed_initialize
- \setupcurrentframed[#2]% here !
\pack_framed_process_indeed}
+\aliased\let\localframedwithsettings\localframed
+
% done
-\def\c!fr!analyze{fr:analyze} % private option
+\defineinterfaceconstant {fr!analyze} {fr:analyze} % private option
\let\delayedbegstrut\relax
\let\delayedendstrut\relax
@@ -1030,7 +1001,7 @@
\let\localformat\empty
\let\localstrut \empty
-\unexpanded\def\pack_framed_process_indeed
+\protected\def\pack_framed_process_indeed
{\d_framed_frameoffset\framedparameter\c!frameoffset
\edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
\d_framed_backgroundoffset
@@ -1052,7 +1023,8 @@
\edef\localwidth {\framedparameter\c!width}%
\edef\localheight{\framedparameter\c!height}%
\edef\localformat{\framedparameter\c!align}%
- \edef\localstrut {\framedparameter\c!strut}%
+ %
+ \edef\p_strut {\framedparameter\c!strut}%
% these are not
\edef\p_framed_autostrut {\framedparameter\c!autostrut}%
\edef\p_framed_frame {\framedparameter\c!frame}%
@@ -1131,48 +1103,48 @@
% i.e. disable (colsetbackgroundproblemintechniek)
\advance\d_framed_width -2\d_framed_local_offset
\advance\d_framed_height -2\d_framed_local_offset
- \ifcsname\??framedstrutalternative\localstrut\endcsname
+ \ifcsname\??framedstrutalternative\p_strut\endcsname
\lastnamedcs
\else
\framed_offset_alternative_unknown
\fi
% the next check could move to strutalternative
\ifcase\c_framed_has_strut % none (not even noindent)
- \let\localbegstrut\relax
- \let\localendstrut\relax
- \let\localstrut \relax
+ \enforced\let\localbegstrut\relax
+ \enforced\let\localendstrut\relax
+ \enforced\let\localstrut \relax
\or % no / overlay
- \let\localbegstrut\pseudobegstrut
- \let\localendstrut\pseudoendstrut
- \let\localstrut \pseudostrut
+ \enforced\let\localbegstrut\pseudobegstrut
+ \enforced\let\localendstrut\pseudoendstrut
+ \enforced\let\localstrut \pseudostrut
\else
- \let\localbegstrut\begstrut
- \let\localendstrut\endstrut
- \let\localstrut \strut
+ \enforced\let\localbegstrut\begstrut
+ \enforced\let\localendstrut\endstrut
+ \enforced\let\localstrut \strut
\fi
\ifx\p_framed_autostrut\v!yes
- \let\delayedbegstrut\relax
- \let\delayedendstrut\relax
- \let\delayedstrut \relax
+ \enforced\let\delayedbegstrut\relax
+ \enforced\let\delayedendstrut\relax
+ \enforced\let\delayedstrut \relax
\else
- \let\delayedbegstrut\localbegstrut
- \let\delayedendstrut\localendstrut
- \let\delayedstrut \localstrut
- \let\localbegstrut \relax
- \let\localendstrut \relax
- \let\localstrut \relax
+ \enforced\let\delayedbegstrut\localbegstrut
+ \enforced\let\delayedendstrut\localendstrut
+ \enforced\let\delayedstrut \localstrut
+ \enforced\let\localbegstrut \relax
+ \enforced\let\localendstrut \relax
+ \enforced\let\localstrut \relax
\fi
\ifconditional\c_framed_has_height
- \let\\\pack_framed_vboxed_newline
+ \enforced\let\\\pack_framed_vboxed_newline
\ifconditional\c_framed_has_width
- \let\hairline\pack_framed_vboxed_hairline
+ \enforced\let\hairline\pack_framed_vboxed_hairline
\ifconditional\c_framed_has_format
\let\next\pack_framed_format_format_yes
\else
\let\next\pack_framed_format_format_nop
\fi
\else
- \let\hairline\pack_framed_hboxed_hairline
+ \enforced\let\hairline\pack_framed_hboxed_hairline
\ifconditional\c_framed_has_format
\let\next\pack_framed_format_format_height
\else
@@ -1181,17 +1153,17 @@
\fi
\orelse\ifconditional\c_framed_has_width
\ifconditional\c_framed_has_format
- \let\hairline\pack_framed_vboxed_hairline
- \let\\\pack_framed_vboxed_newline
+ \enforced\let\\\pack_framed_vboxed_newline
+ \enforced\let\hairline\pack_framed_vboxed_hairline
\let\next\pack_framed_format_format_width
\else
- \let\hairline\pack_framed_hboxed_hairline
- \let\\\pack_framed_hboxed_newline
+ \enforced\let\\\pack_framed_hboxed_newline
+ \enforced\let\hairline\pack_framed_hboxed_hairline
\let\next\pack_framed_format_format_hsize
\fi
\else
- \let\hairline\pack_framed_hboxed_hairline
- \let\\\pack_framed_hboxed_newline
+ \enforced\let\\\pack_framed_hboxed_newline
+ \enforced\let\hairline\pack_framed_hboxed_hairline
\let\next\pack_framed_format_format_no_size
\fi
\pack_framed_check_extra_offsets
@@ -1466,7 +1438,7 @@
\fi
\fi}
-\unexpanded\def\pack_framed_finish
+\protected\def\pack_framed_finish
{%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down
\pack_framed_locator_before\p_framed_location
\ifconditional\c_framed_has_format
@@ -1845,16 +1817,7 @@
%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the
%D running text.
-\unexpanded\def\inframed
- {\dosingleempty\pack_framed_inline}
-
-% \def\pack_framed_inline[#1]%
-% {\framed[\c!location=\v!low,#1]}
-%
-% or:
-
-\def\pack_framed_inline[%
- {\framed[\c!location=\v!low,}
+\permanent\tolerant\protected\def\inframed[#1]{\framed[\c!location=\v!low,#1]}
%D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background,
%D but no content, so actually we have a sort of phantom framed box.
@@ -1900,7 +1863,7 @@
\newcount\c_framed_mstyle
-\unexpanded\def\pack_framed_math_strut
+\protected\def\pack_framed_math_strut
{\Ustartmath
\triggermathstyle\c_framed_mstyle
\vphantom{(}%
@@ -1910,18 +1873,18 @@
\installframedcommandhandler \??mathframed {mathframed} \??mathframed
+\newcount\c_pack_framed_mathframed
+\newtoks \t_pack_framed_mathframed
+
\appendtoks
\setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}%
\to \everydefinemathframed
-\unexpanded\def\pack_framed_mathframed#1%
+\protected\def\pack_framed_mathframed#1%
{\begingroup
\edef\currentmathframed{#1}%
\dosingleempty\pack_framed_mathframed_indeed}
-\newcount\c_pack_framed_mathframed
-\newtoks \t_pack_framed_mathframed
-
\def\pack_framed_math_pos
{\global\advance\c_pack_framed_mathframed\plusone
\xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}%
@@ -1935,9 +1898,9 @@
\c_framed_mstyle\normalmathstyle
\edef\m_framed_location{\mathframedparameter\c!location}%
\ifx\m_framed_location\v!mathematics
- \let\normalstrut\pack_framed_math_pos
+ \enforced\let\normalstrut\pack_framed_math_pos
\orelse\ifx\m_framed_location\v!low\else
- \let\normalstrut\pack_framed_math_strut
+ \enforced\let\normalstrut\pack_framed_math_strut
\fi
\inheritedmathframedframed\bgroup
\Ustartmath
@@ -2112,29 +2075,29 @@
\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
-\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
+\permanent\protected\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
{\ifconditional\raggedonelinerstate
\expandafter\dodoformatonelinerbox
\else
\expandafter\nodoformatonelinerbox
\fi}
-\def\dodoformatonelinerbox
+\permanent\protected\def\dodoformatonelinerbox
{\afterassignment\redoformatonelinerbox
\setbox\nextbox\hbox} % maybe \hpack
-\def\redoformatonelinerbox
+\permanent\protected\def\redoformatonelinerbox
{\aftergroup\dododoformatonelinerbox
\ignorespaces}
-\def\dododoformatonelinerbox
+\permanent\protected\def\dododoformatonelinerbox
{\hpack to \hsize % was \hbox
{\ifcase\raggedstatus\or\hss\or\hss \fi
\unhbox\nextbox \removeunwantedspaces
\ifcase\raggedstatus\or \or\hss\or\hss\fi}%
\egroup}
-\def\nodoformatonelinerbox % grabs {
+\permanent\protected\def\nodoformatonelinerbox % grabs {
{\let\next=}
%D The handlers:
@@ -2177,13 +2140,10 @@
\pack_framed_do_setups
\raggedcommand
\pack_framed_do_top
- \bgroup
\synchronizeinlinedirection
\localbegstrut
- %\aftergrouped{\localendstrut\pack_framed_do_bottom\egroup}%
- \aftergroup\localendstrut
- \aftergroup\pack_framed_do_bottom
- \aftergroup\egroup
+ \atendofgroup\localendstrut
+ \atendofgroup\pack_framed_do_bottom
\doformatonelinerbox}
\def\pack_framed_format_format_nop
@@ -2200,12 +2160,10 @@
\pack_framed_do_setups
\raggedcenter
\vss
- \bgroup
\synchronizeinlinedirection
\localbegstrut
- \aftergroup\localendstrut
- \aftergroup\vss
- \aftergroup\egroup
+ \atendofgroup\localendstrut
+ \atendofgroup\vss
\doformatonelinerbox}
\def\pack_framed_format_format_height
@@ -2220,12 +2178,10 @@
\pack_framed_do_setups
\raggedcommand
\vss
- \bgroup
- \aftergroup\localendstrut
- \aftergroup\vss
- \aftergroup\egroup
\synchronizeinlinedirection
\localbegstrut
+ \atendofgroup\localendstrut
+ \atendofgroup\vss
\doformatonelinerbox}
\def\pack_framed_format_format_width
@@ -2241,12 +2197,10 @@
\pack_framed_do_setups
\raggedcommand
\pack_framed_do_top
- \bgroup
\synchronizeinlinedirection
\localbegstrut
- \aftergroup\localendstrut
- \aftergroup\pack_framed_do_bottom
- \aftergroup\egroup
+ \atendofgroup\localendstrut
+ \atendofgroup\pack_framed_do_bottom
\doformatonelinerbox}
\def\pack_framed_format_format_vsize
@@ -2260,9 +2214,7 @@
\vsize\d_framed_height
\pack_framed_do_setups
\vss
- \bgroup
- \aftergroup\vss
- \aftergroup\egroup
+ \atendofgroup\vss
\hbox
\bgroup
\aftergroup\egroup
@@ -2282,9 +2234,7 @@
\hss
\synchronizeinlinedirection
\localstrut
- \bgroup
- \aftergroup\hss
- \aftergroup\egroup
+ \atendofgroup\hss
\doformatonelinerbox}
\def\pack_framed_format_format_no_size
@@ -2465,7 +2415,7 @@
%D These macros try to adapt their behaviour as good as possible to the circumstances
%D and act as natural as possible.
-\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
+\protected\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
{\begingroup
\scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
\scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax
@@ -2489,7 +2439,7 @@
\localbegstrut
\endgroup}
-\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
+\protected\def\pack_framed_hboxed_hairline % use framed dimen
{\bgroup
\scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
\ifconditional\c_framed_has_height
@@ -2513,10 +2463,10 @@
%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In
%D horizontal boxes it expands to a space.
-\unexpanded\def\pack_framed_vboxed_newline
+\protected\def\pack_framed_vboxed_newline
{\endgraf\ignorespaces}
-\unexpanded\def\pack_framed_hboxed_newline
+\protected\def\pack_framed_hboxed_newline
{\unskip\normalspace\ignorespaces}
%D We can set each rule on or off. The default setting is inherited from
@@ -2699,7 +2649,7 @@
\letframedtextparameter\c!right\relax
\settrue\c_framed_text_location_none}
-\unexpanded\def\pack_framed_text_start#1%
+\protected\def\pack_framed_text_start#1%
{\bgroup
\edef\currentframedtext{#1}%
\dodoubleempty\pack_framed_text_start_indeed}
@@ -2726,7 +2676,7 @@
% \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used
\letframedtextparameter\c!strut\v!no
\inheritedframedtextframed\bgroup
- \let\\=\endgraf
+ \enforced\let\\\endgraf
\edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}%
\ifx\p_framed_text_depthcorrection\v!on
\pack_framed_text_start_depth_correction
@@ -2753,7 +2703,7 @@
\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
-\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
+\protected\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
{\endgraf
\removelastskip
\ifx\p_framed_text_depthcorrection\v!on
@@ -2833,7 +2783,7 @@
%D The simple brace (or group) delimited case is typeset slightly different
%D and is not aligned.
-\unexpanded\def\pack_framed_text_direct#1%
+\protected\def\pack_framed_text_direct#1%
{\bgroup
\edef\currentframedtext{#1}%
\dosingleempty\pack_framed_text_start_direct}
@@ -2847,7 +2797,7 @@
\letframedtextparameter\c!strut\v!no
\inheritedframedtextframed\bgroup
\blank[\v!disable]%
- \let\\=\endgraf
+ \enforced\let\\\endgraf
\useframedtextstyleandcolor\c!style\c!color
\vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1
\framedtextparameter\c!inner
@@ -2896,7 +2846,7 @@
\newcount\c_temp_framed_crap
-\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
+\permanent\tolerant\protected\def\pack_framed_defined_process[#1]#*[#2]% official (not much checking, todo: parent)
{\bgroup
\ifcsname\??regularframedlevel#1\endcsname
%\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
@@ -2905,16 +2855,11 @@
\let\c_pack_framed_temp\c_temp_framed_crap
\fi
\advance\c_pack_framed_temp\plusone
- \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
+ \defcsname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
\bgroup
\edef\currentframed{#1>\the\c_pack_framed_temp}%
\pack_framed_initialize
- \dosingleempty\pack_framed_defined_process_indeed}
-
-\def\pack_framed_defined_process_indeed[#1]%
- {\iffirstargument % faster
- \setupcurrentframed[#1]% here !
- \fi
+ \setupcurrentframed[#2]% here !
\pack_framed_process_indeed}
\let\placeframed\pack_framed_defined_process % new per 2012/04/23
@@ -2980,17 +2925,16 @@
%\c!width=\v!fit,
\c!offset=\v!overlay]
-\unexpanded\def\startframedcontent
- {\dosingleempty\pack_framed_start_content}
+\permanent\let\stopframedcontent\relax
-\def\pack_framed_start_content[#1]%
+\permanent\tolerant\protected\def\startframedcontent[#1]%
{\bgroup
\edef\currentframedcontent{#1}%
\ifx\currentframedcontent\v!off
- \let\stopframedcontent\egroup
+ \enforced\let\stopframedcontent\egroup
\else
\checkframedcontentparent
- \let\stopframedcontent\pack_framed_stop_content_indeed
+ \enforced\let\stopframedcontent\pack_framed_stop_content_indeed
\expandafter\pack_framed_start_content_indeed
\fi}
@@ -3011,7 +2955,7 @@
\forgetall
\blank[\v!disable]}
-\def\pack_framed_stop_content_indeed
+\protected\def\pack_framed_stop_content_indeed
{\removelastskip
\egroup
\vskip\scratchbottomoffset
@@ -3040,8 +2984,6 @@
%D A Goodie:
-\def\v!unframed{unframed}
-
\defineframed
[\v!unframed]
[\c!frame=\v!off,
@@ -3058,9 +3000,9 @@
\let\themaxboxwidth\clf_themaxboxwidth
-%D Fast enough for most cases:
+%D Fast enough for most cases (we could do a massive \type {\ifhastok} instead):
-\unexpanded\def\doifelseframed#1%
+\protected\def\doifelseframed#1%
{\iftok{#1\c!frame }{\v!on}\expandafter\firstoftwoarguments
\orelse\iftok{#1\c!topframe }{\v!on}\expandafter\firstoftwoarguments
\orelse\iftok{#1\c!bottomframe}{\v!on}\expandafter\firstoftwoarguments
diff --git a/tex/context/base/mkiv/page-bck.mkxl b/tex/context/base/mkiv/page-bck.mkxl
new file mode 100644
index 000000000..9f9c5ee03
--- /dev/null
+++ b/tex/context/base/mkiv/page-bck.mkxl
@@ -0,0 +1,715 @@
+%D \module
+%D [ file=page-bck, % copied from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% Currently the text cells are fakes and no (foreground) frames which makes sense
+% as order might matter e.g. is text sticks in other cells. The page, text etc
+% areas do support foreground order change.
+
+\writestatus{loading}{ConTeXt Page Macros / Backgrounds}
+
+\unprotect
+
+% maybe use \currentframedhash here
+
+%D For special purposes, users can question the \type {*background} mode. This mode
+%D is only available when typesetting the pagebody.
+%D
+%D \starttyping
+%D \startmode[*background] ...
+%D \stoptyping
+
+\newconditional\c_page_backgrounds_new
+\newconditional\c_page_backgrounds_new_right
+\newconditional\c_page_backgrounds_new_left
+\newconditional\c_page_backgrounds_some
+
+\appendtoks
+ \ifconditional\c_page_backgrounds_some
+ \ifconditional\c_page_backgrounds_new
+ \setsystemmode\v!background
+ \fi
+ \fi
+\to \everybeforepagebody
+
+\protected\def\initializepagebackgrounds
+ {\setfalse\c_page_backgrounds_new
+ \setfalse\c_page_backgrounds_new_right
+ \setfalse\c_page_backgrounds_new_left
+ \setfalse\c_page_backgrounds_some}
+
+%D We keep calculations and checks to a minimum and also try to minimize
+%D the amount of tracing due to expansion.
+
+\let\currentotrbackground\empty
+
+%D This is the only spot where we have a low level dependency on the way
+%D parent chains are defined but we want the speed.
+
+\protected\def\page_backgrounds_check_background
+ {\ifcsname\??framed\currentotrbackground:\c!background\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\empty
+ \expandafter\expandafter\expandafter\page_backgrounds_check_frame
+ \else
+ \page_backgrounds_set_yes
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_frame
+ \fi}
+
+\def\page_backgrounds_check_frame
+ {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_leftframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_leftframe
+ \fi}
+
+\def\page_backgrounds_check_leftframe
+ {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_rightframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_rightframe
+ \fi}
+
+\def\page_backgrounds_check_rightframe
+ {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_topframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_topframe
+ \fi}
+
+\def\page_backgrounds_check_topframe
+ {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_bottomframe
+ \fi
+ \else
+ \expandafter\page_backgrounds_check_bottomframe
+ \fi}
+
+\def\page_backgrounds_check_bottomframe
+ {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname
+ %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}%
+ \edef\page_background_temp{\lastnamedcs}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \page_backgrounds_set_nop
+ \fi
+ \else
+ \page_backgrounds_set_nop
+ \fi}
+
+%D We don't use the commandhandler code as we want these multitude of backgrounds to be
+%D as fast as possible.
+
+\installcorenamespace{layoutbackgrounds}
+\installcorenamespace{layoutbackgroundcheck} % we need another hash as \??layoutbackgrounds<...> gets defined
+
+\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax }
+\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined}
+
+\protected\def\page_backgrounds_check#1%
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \page_backgrounds_check_background}
+
+\permanent\def\doifelsesomebackground#1%
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\aliased\let\doifsomebackgroundelse\doifelsesomebackground
+
+\permanent\def\doifsomebackground#1%
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D The background mechanism falls back on the \type {\framed} macro. This means
+%D that all normal frame and overlay features can be used.
+
+\def\page_backgrounds_add_to_box#1% area
+ {\ifcsname\??layoutbackgrounds#1\endcsname
+ \expandafter\page_backgrounds_add_to_box_indeed
+ \else
+ \expandafter\gobblefourarguments
+ \fi#1}
+
+%D We don't need the dimensions here as this is a real framed but the question is:
+%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only
+%D for hidden).
+
+\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero
+ {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
+ \fi
+ % #2 has the right dimensions already
+ \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground)
+
+
+%D There are quite some backgrounds. At the bottom layer, there is the {\em paper}
+%D background. This one is only used for special purposes, like annotations to
+%D documents.
+
+\def\page_backgrounds_add_to_print#1%
+ {\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight}
+
+%D The page backgrounds can be put behind the {\em left page}, the {\em right page}
+%D or {\em each page}. As with the paper background, these are calculated on each
+%D page.
+
+\def\page_backgrounds_add_to_paper#1%
+ {\doifbothsidesoverruled
+ {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}%
+ {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}%
+ {\page_backgrounds_add_to_box\v!leftpage #1\paperwidth\paperheight}%
+ \page_backgrounds_add_to_box\v!page#1\paperwidth\paperheight}
+
+%D Then there are the 25 areas that make up the layout: {\em top, header, text,
+%D footer, bottom} times {\em left edge, left margin, text, right margin, right
+%D edge}. These are only recalculated when they change or when the \type {status}
+%D is set to \type {repeat}.
+
+\newbox\leftbackground % todo: rename
+\newbox\rightbackground % todo: rename
+
+%D Finaly there is an aditional {\em text} background, again useful for special
+%D purposes only. This one is calculated each time. The hidden backgrounds are not
+%D meant for users!
+
+\newconditional\c_page_backgrounds_hidden_enabled
+
+\def\page_backgrounds_add_to_text#1%
+ {\ifconditional\c_page_backgrounds_hidden_enabled
+ \page_backgrounds_add_to_box\v!hidden#1\makeupwidth\textheight % mine !
+ \fi
+ \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight}
+
+%D The next couple of macros implement the area backgrounds. As said, these are
+%D cached in dedicated boxes. The offsets and depth of the page are used for
+%D alignment purposes.
+
+%newdimen\pageoffset % bleed
+%newdimen\pagedepth % built-in
+
+%D We need a bit more clever mechanism in order to handle layers well. This means
+%D that we cannot calculate both background at the same time since something may
+%D have changed halfway a page.
+
+%D Margin swapping has been simplified: see mkii code in case of regression.
+%D Calculation is delayed till the page anyway so the state is known.
+
+\def\page_backgrounds_recalculate
+ {\global\settrue\c_page_backgrounds_new}
+
+\def\page_backgrounds_set_boxes
+ {\ifconditional\c_page_backgrounds_new
+ \page_backgrounds_set_boxes_r
+ \fi
+ \doifbothsides
+ \page_backgrounds_set_boxes_a
+ \page_backgrounds_set_boxes_b
+ \page_backgrounds_set_boxes_c
+ \ifx\p_page_backgrounds_state\v!repeat\else
+ \global\setfalse\c_page_backgrounds_new
+ \fi}
+
+\def\page_backgrounds_set_boxes_r
+ {\global\settrue\c_page_backgrounds_new_right
+ \global\settrue\c_page_backgrounds_new_left
+ \global\setbox\leftbackground\emptybox
+ \global\setbox\rightbackground\emptybox}
+
+\def\page_backgrounds_set_boxes_a
+ {\ifconditional\c_page_backgrounds_new_left
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\leftbackground % \conditionalfalse
+ \global\setfalse\c_page_backgrounds_new_left
+ \global\setfalse\c_page_backgrounds_new_right
+ \fi}
+
+\def\page_backgrounds_set_boxes_b
+ {\ifconditional\c_page_backgrounds_new_left
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\leftbackground
+ \global\setfalse\c_page_backgrounds_new_left
+ \fi}
+
+\def\page_backgrounds_set_boxes_c
+ {\ifconditional\c_page_backgrounds_new_right
+ % \showmessage\m!layouts8\empty
+ \page_backgrounds_set_box\rightbackground
+ \global\setfalse\c_page_backgrounds_new_right
+ \fi}
+
+\def\page_backgrounds_add_to_main#1% todo: dimension spec
+ {\ifconditional\c_page_backgrounds_some
+ \page_backgrounds_set_boxes
+ \setbox#1\vpack
+ {\offinterlineskip
+ \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}%
+ \box#1}%
+ \fi}
+
+\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE
+\newdimen\pagebackgroundvoffset
+\newdimen\pagebackgroundoffset % used elsewhere
+\newdimen\pagebackgrounddepth
+\newdimen\pagebackgroundcompensation
+
+\def\page_backgrounds_set_offsets % used in menus (we can use ifcsname's here)
+ {\ifconditional\c_page_backgrounds_some \ifconditional\c_page_backgrounds_new
+ \page_backgrounds_set_offsets_indeed % indirect, less tracing
+ \fi \fi}
+
+\def\page_backgrounds_set_offsets_indeed
+ {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \orelse\ifcsname\??layoutbackgrounds\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \else
+ \page_backgrounds_set_offsets_nop
+ \fi}
+
+\def\page_backgrounds_set_offsets_nop
+ {\global\pagebackgroundhoffset \zeropoint
+ \global\pagebackgroundvoffset \zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \global\pagebackgroundcompensation\zeropoint}
+
+\def\page_backgrounds_set_offsets_yes
+ {\global\pagebackgroundoffset \d_page_backgrounds_depth
+ \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax
+ \ifzeropt\pagebackgroundcompensation
+ \page_backgrounds_set_offsets_nop
+ \else
+ \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \orelse\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \else
+ \global\pagebackgroundhoffset\pagebackgroundcompensation
+ \fi
+ \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \orelse\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \else
+ \global\pagebackgroundvoffset\pagebackgroundcompensation
+ \global\pagebackgrounddepth \d_page_backgrounds_depth
+ \fi
+ \fi}
+
+\appendtoks
+ \page_backgrounds_set_offsets
+\to \everybeforepagebody
+
+\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
+
+%D The swapping here is pretty nasty! Maybe we should find another way some day but
+%D for now we tweak.
+
+\def\page_backgrounds_set_box#1% #2%
+ {\global\setbox#1\vpack
+ {\dontcomplain
+ \swapmargins
+ \ifconditional\swapbackgroundmargins
+ \doifelsemarginswap \donothing
+ {\enforced\swapcsvalues\v!rightmargin\v!leftmargin
+ \enforced\swapcsvalues\v!rightedge \v!leftedge}%
+ \fi
+ \calculatereducedvsizes
+ \offinterlineskip
+ % \ifconditional#2\relax
+ % \doswapmargins % hm, this one gets nilled in \swapmargins anyway
+ % \fi
+ \ifdim\topheight>\zeropoint
+ \kern\dimexpr-\topheight-\topdistance\relax
+ \page_backgrounds_set_box_row\v!top\topheight
+ \kern\topdistance
+ \fi
+ \ifdim\headerheight>\zeropoint
+ \page_backgrounds_set_box_row\v!header\headerheight
+ \kern\headerdistance
+ \fi
+ \ifdim\textheight>\zeropoint
+ \page_backgrounds_set_box_row\v!text\textheight
+ \fi
+ \ifdim\footerheight>\zeropoint
+ \kern\footerdistance
+ \page_backgrounds_set_box_row\v!footer\footerheight
+ \fi
+ \ifdim\bottomheight>\zeropoint
+ \kern\bottomdistance
+ \page_backgrounds_set_box_row\v!bottom\bottomheight
+ \fi
+ \vfilll}%
+ \smashbox#1}
+
+\def\page_backgrounds_set_box_row#1#2% maybe helper
+ {\setbox\scratchbox\vpack to #2
+ \bgroup\hpack\bgroup
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2%
+ \else
+ \kern\leftedgewidth
+ \fi
+ \kern\leftedgedistance
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2%
+ \else
+ \kern\leftmarginwidth
+ \fi
+ \kern\leftmargindistance
+ \fi
+ \ifcsname\??layoutbackgrounds#1\v!text\endcsname
+ \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2%
+ \else
+ \kern\makeupwidth
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ \kern\rightmargindistance
+ \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname
+ \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2%
+ \else
+ \kern\rightmarginwidth
+ \fi
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \kern\rightedgedistance
+ \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname
+ \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2%
+ \else
+ \kern\rightedgewidth
+ \fi
+ \fi
+ \egroup\egroup
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\relax}
+
+% these are fake framed .. maybe it's nicer to honor foreground here as well
+% but it's probably a slow downer
+
+\def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height
+ {\begingroup
+ \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
+ \fi
+ \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}%
+ \ifx\p_page_backgrounds_command\empty
+ \expandafter\page_backgrounds_set_box_cell_nop
+ \else
+ \expandafter\page_backgrounds_set_box_cell_yes
+ \fi#3#4%
+ \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox
+ \endgroup}
+
+\def\page_backgrounds_set_box_cell_nop#1#2%
+ {\setbox\scratchbox\emptyvbox
+ \wd\scratchbox#1%
+ \ht\scratchbox#2}
+
+\def\page_backgrounds_set_box_cell_yes#1#2%
+ {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}%
+ \dp\scratchbox\zeropoint}
+
+%D The background mechanism is quite demanding in terms or resources. We used to
+%D delay these definitions till runtime usage, but since today's \TEX's are large,
+%D we now do the work on forehand.
+%D
+%D \starttyping
+%D \setupbackgrounds [settings]
+%D \setupbackgrounds [paper,page,text,..] [settings]
+%D \setupbackgrounds [top,...] [leftedge,...] [settings]
+%D \stoptyping
+%D
+%D \showsetup{setupbackgrounds}
+%D
+%D Because the number of arguments runs from one to three, we need to check
+%D for it.
+
+\newtoks\everybackgroundssetup
+
+% \permanent\protected\def\setupbackgrounds
+% {\dotripleempty\page_backgrounds_setup}
+%
+% \def\page_backgrounds_setup
+% {\ifthirdargument
+% \expandafter\page_backgrounds_setup_double
+% \orelse\ifsecondargument
+% \expandafter\page_backgrounds_setup_single
+% \orelse\iffirstargument
+% \expandafter\page_backgrounds_setup_basics
+% \fi}
+
+\permanent\tolerant\protected\def\setupbackgrounds[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ \expandafter\gobblethreeoptionals
+ \or
+ \expandafter\page_backgrounds_setup_basics
+ \or
+ \expandafter\page_backgrounds_setup_single
+ \or
+ \expandafter\page_backgrounds_setup_double
+ \fi[#1][#2][#3]}
+
+\newdimen\d_page_backgrounds_offset
+\newdimen\d_page_backgrounds_depth
+
+\appendtoks
+ \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}%
+ \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }%
+ \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }%
+ \global\d_page_backgrounds_offset\ifx\p_offset\empty\zeropoint\else\p_page_backgrounds_offset\fi
+ \global\d_page_backgrounds_depth \ifx\p_depth \empty\zeropoint\else\p_page_backgrounds_depth \fi
+ \global\pagebackgroundoffset\d_page_backgrounds_offset\relax
+ \global\pagebackgrounddepth \d_page_backgrounds_depth \relax
+ \ifx\p_page_backgrounds_state\v!stop
+ \global\setfalse\c_page_backgrounds_new
+ \else
+ \global\settrue \c_page_backgrounds_new
+ \fi
+\to \everybackgroundssetup
+
+\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage}
+\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
+\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge}
+
+\protected\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up
+ {\global\settrue\c_page_backgrounds_some
+ \def\page_backgrounds_setup_step##1%
+ {\doifelseinset{##1}\v_page_backgrounds_double_set
+ {\page_backgrounds_setup_and_check{##1}{#3}}
+ {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}%
+ \processcommacommand[#2]\page_backgrounds_setup_step_nested}}%
+ \processcommacommand[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}
+
+\protected\def\page_backgrounds_setup_single[#1][#2][#3]%
+ {\global\settrue\c_page_backgrounds_some
+ \doifelsecommon{#1}\v_page_backgrounds_single_set
+ {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}%
+ \processcommacommand[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}%
+ {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}}
+
+\protected\def\page_backgrounds_setup_basics[#1][#2][#3]%
+ {\setupframed[\??layoutbackgrounds][#1]%
+ \the\everybackgroundssetup}
+
+\protected\def\page_backgrounds_setup_and_check#1#2% tag settings
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \setupframed[\currentotrbackground][#2]%
+ \page_backgrounds_check_background}
+
+%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level
+%D framed object associated.
+
+\definesimplifiedframed[\??layoutbackgrounds\v!paper]
+\definesimplifiedframed[\??layoutbackgrounds\v!page]
+\definesimplifiedframed[\??layoutbackgrounds\v!leftpage]
+\definesimplifiedframed[\??layoutbackgrounds\v!rightpage]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!hidden]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge]
+
+\setupbackgrounds
+ [\v!page]
+ [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere
+ \c!depth=\zeropoint]
+
+%D General setup:
+
+\setupbackgrounds
+ [\c!state=\c!start]
+
+%D The hidden layer can be populated by extending the following comma separated
+%D list. This only happens in core modules.
+
+% todo page-2 .. page+2 achter pagina -> bleed
+% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
+
+\permanent\protected\def\enablehiddenbackground
+ {\global\settrue\c_page_backgrounds_hidden_enabled
+ \global\settrue\c_page_backgrounds_some
+ \page_backgrounds_recalculate}
+
+\permanent\protected\def\disablehiddenbackground
+ {\global\setfalse\c_page_backgrounds_hidden_enabled}
+
+\def\hiddenbackgroundlist
+ {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
+
+\defineoverlay[\v!text-2][\positionregionoverlay\textanchor{\v!text-2}] % no new anchor, we share text
+\defineoverlay[\v!text-1][\positionregionoverlay\textanchor{\v!text-1}]
+\defineoverlay[\v!text+1][\positionregionoverlay\textanchor{\v!text+1}]
+\defineoverlay[\v!text+2][\positionregionoverlay\textanchor{\v!text+2}]
+
+\setupbackgrounds
+ [\v!hidden]
+ [\c!background=\hiddenbackgroundlist]
+
+%D Because we haven't really set up backgrounds yet, we set the main efficiency
+%D switch to false.
+
+\setfalse\c_page_backgrounds_some
+
+%D Sometimes you have a document wide (page) background but need to overload it
+%D locally. In such case (at least in my experience) the only values that get set
+%D are the background and backgroundcolor (if set at all). A full inheritance chain
+%D would complicate things because then we need to use named backgrounds which in
+%D turn will make this mechanism slower. I considered independent local backgrounds
+%D but that also complicates the code (not that much) but isolation means that we
+%D need to set more parameters each time. The following simple approach proabbly
+%D suits most usage.
+%D
+%D \starttyping
+%D \starttext
+%D \setupbackgrounds[page][background=color,backgroundcolor=red]
+%D \input tufte \page
+%D \setupbackgrounds[page][background=,backgroundcolor=]
+%D \input tufte \page
+%D \setupbackgrounds[page][background=color,backgroundcolor=red]
+%D \input tufte \page
+%D \pushbackground[page]
+%D \setupbackgrounds[page][background=color,backgroundcolor=green]
+%D \input tufte \page
+%D \popbackground
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+\permanent\protected\def\pushbackground[#1]%
+ {\pushmacro\popbackground
+ \edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \overloaded\permanent\protected\edef\popbackground
+ {\setupframed
+ [\currentotrbackground]
+ [\c!background=\namedframedparameter{\currentotrbackground}\c!background,
+ \c!backgroundcolor=\namedframedparameter{\currentotrbackground}\c!backgroundcolor]%
+ \page_backgrounds_check_background
+ \popmacro\popbackground}%
+ \setupframed
+ [\currentotrbackground]
+ [\c!background=,\c!backgroundcolor=]%
+ \page_backgrounds_check_background}
+
+\permanent\let\popbackground\relax
+
+\protect \endinput
+
+% %D The next series is used in local (for instance floating) backgrounds.
+%
+% \installsimplifiedframed{\??layoutbackgrounds\v!local}
+%
+% \getparameters
+% [\??layoutbackgrounds\v!local]
+% [\c!component=local,
+% \c!background=\localbackgroundlist]
+%
+% \def\localbackgroundlist
+% {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2}
+%
+% \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] % todo share
+% \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}]
+% \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}]
+% \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}]
+%
+% \def\page_backgrounds_add_local_to_box
+% {\ifconditional\c_page_backgrounds_hidden_enabled
+% \expandafter\page_backgrounds_add_local_to_box_indeed
+% \else
+% \expandafter\gobbleoneargument
+% \fi}
+%
+% \def\page_backgrounds_add_local_to_box_indeed#1%
+% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}%
+% \global\advance\localpositionnumber\plusone} % afterwards !
+%
+% \let\page_backgrounds_add_local_to_box\gobbleoneargument
+
+% Test how previous macro behaves with depth:
+%
+% \startcolumnset
+% \input tufte
+% \placefigure{none}{\framed[lines=5]{xxx}}
+% \input tufte
+% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate}
+% \input tufte
+% \stopcolumnset
+
diff --git a/tex/context/base/mkiv/page-ini.mkxl b/tex/context/base/mkiv/page-ini.mkxl
new file mode 100644
index 000000000..6a9b75d22
--- /dev/null
+++ b/tex/context/base/mkiv/page-ini.mkxl
@@ -0,0 +1,376 @@
+%D \module
+%D [ file=page-ini,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Initializations}
+
+\registerctxluafile{page-ini}{}
+
+%D The \type {\processpage} command has become obsolete. It's original
+%D purpose was to flush only parts of a document but nowadays we have
+%D project structure and modes. This is just one of those very early
+%D features that no longer makes sense.
+
+%D The \type {\couplepage} command has become obsolete. It's original
+%D purpose was to provide hooks for printer directives (like choosing
+%D different paper trays).
+
+\unprotect
+
+%D Shipout control.
+
+\newcount\nofshipouts
+
+\appendtoks
+ \global\advance\nofshipouts\plusone
+\to \everyaftershipout
+
+\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled
+
+\protected\def\page_otr_shipout % not used at all
+ {\ifconditional\c_otr_shipout_enabled
+ \expandafter\page_otr_shipout_yes
+ \else
+ \expandafter\page_otr_shipout_nop
+ \fi}
+
+\aliased\let\page_otr_shipout_yes\normalshipout
+
+\protected\def\page_otr_shipout_nop
+ {\writestatus\m!system{ignoring shipout of real page \the\realpageno}%
+ \global\advance\realpageno\minusone % else no flush of resources
+ \dowithnextbox{\deadcycles\zerocount}}
+
+% We don't support direct user \shipouts (weird: this does not work, bug?)
+%
+% \let\shipout\page_otr_shipout_nop
+
+%D Building pages.
+
+\newbox\pagebox
+
+% \ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi
+% \ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi
+% \ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi
+
+\newtoks\t_page_postprocessors_box
+\newtoks\t_page_postprocessors_page
+\newtoks\t_page_postprocessors_column
+
+\newconstant\b_page_postprocessor
+
+\def\page_apply_postprocessors_box#1%
+ {\b_page_postprocessor#1\relax
+ \the\t_page_postprocessors_box}
+
+\def\page_apply_postprocessors_page#1%
+ {\b_page_postprocessor#1\relax
+ \the\t_page_postprocessors_page}
+
+\def\page_apply_postprocessors_column#1%
+ {\b_page_postprocessor#1\relax
+ \the\t_page_postprocessors_column}
+
+%D Floats.
+
+\def\page_otr_flush_all_floats
+ {%\flushnotes already done
+ \ifconditional\c_page_floats_some_waiting
+ \page_otr_command_flush_all_floats
+ \fi}
+
+\def\page_otr_insert_dummy_page
+ {\par
+ \ifvmode
+ \page_otr_flush_all_floats
+ \fixedspace
+ \vfill
+ \page_otr_command_next_page
+ \fi}
+
+\def\page_otr_flush_pending_content
+ {\vkern\zeropoint\relax
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \penalty\outputpenalty
+ \fi}
+
+\newconstant\c_page_postponed_mode % \c_page_postponed_mode\plusone
+\newbox \b_page_otr_saved
+
+\installoutputroutine\savepagecontent
+ {\global\setbox\b_page_otr_saved\box\normalpagebox}
+
+\permanent\protected\def\flushpagecontent
+ {\ifvoid\b_page_otr_saved\else\unvbox\b_page_otr_saved\fi}
+
+% Test case: assumes one group level for output routine, todo:
+% a toks.
+%
+% \starttext
+%
+% \startbuffer[makeup]
+% \startpagemakeup[pagestate=start,page=no]
+% \color[red]{
+% \vfill
+% \dorecurse{3}{
+% \samplefile{klein}
+% \vfill
+% }
+% }
+% \stoppagemakeup
+% \stopbuffer
+%
+% \startcolor[green]
+% \dorecurse{10}{
+% \dontleavehmode{\bf 1:#1:} \samplefile{sapolsky}\par
+% }
+% \stopcolor
+%
+% \startpostponing % [+3]
+% \getbuffer[makeup]
+% \stoppostponing
+%
+% \startcolor[blue]
+% \dorecurse{25}{
+% \dontleavehmode{\bf 2:#1:} \samplefile{sapolsky}\par
+% }
+% \stopcolor
+%
+% \stoptext
+
+\def\page_otr_construct_and_shipout#1#2#3%
+ {\forgetall
+ \page_boxes_shipout{\page_boxes_constructed_page#1#2}% \hbox removed
+ \page_otr_flush_pending_content
+ % not really needed, replaced by \flushsavedfloats
+ \page_otr_check_for_pending_inserts
+ % but does not hurt either (we're still in the otr!)
+ \inpagebodytrue % needed for enabling \blank ! brrr
+ \pagebodymode\plusone % todo: \plustwo when spread
+ \page_otr_command_flush_saved_floats
+ \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns
+ \strc_pagenumbers_increment_counters % should hook into an every
+ \page_adapts_synchronize
+ \page_otr_check_for_pending_inserts
+ \page_otr_command_flush_facing_floats
+ \page_floats_flush_page_floats % before postponed blocks
+ \page_spread_flush % defined later
+ \ifnum#3=\plusone
+ % this is tricky! we need to make sure we are in the output group
+ \ifnum\c_page_postponed_mode=\plusone
+ \aftergroup\page_postponed_blocks_flush
+ \else
+ \page_postponed_blocks_flush
+ \fi
+ \else
+ \page_postponed_blocks_flush
+ \fi}
+
+% Can't we get rid of this hackery? It's used in some widgets
+% stuff so probably not.
+
+\newbox\b_page_otr_special
+
+\def\page_otr_flush_special_content
+ {\ifvoid\b_page_otr_special \else
+ \box\b_page_otr_special
+ \fi}
+
+\def\page_otr_add_special_content
+ {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox}
+
+\def\page_otr_add_special_content_indeed
+ {\wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \global\setbox\b_page_otr_special\hbox
+ {%\hskip-\maxdimen % not here, fails in acrobat (clips)
+ \box\b_page_otr_special\box\nextbox}}% was \unhbox, is now box again
+
+\let\flushatshipout\page_otr_add_special_content
+
+\maxdeadcycles=1000
+
+\newtoks\afterpage \newtoks\aftereverypage
+\newtoks\beforepage \newtoks\beforeeverypage
+
+\newif\ifarrangingpages \arrangingpagesfalse
+
+\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off
+
+% \appendtoks
+% \ifcase\pageornamentstate \or
+% \pageornamentstate\zerocount
+% \fi
+% \to \everyaftershipout
+
+\appendtoks
+ \ifcase\pageornamentstate \or
+ \global\pageornamentstate\zerocount
+ \fi
+\to \everyaftershipout
+
+% Mark synchronization
+
+\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages
+
+\def\page_marks_synchronize_page#1% box
+ {\strc_markings_synchronize[\v!page][#1][\ifconditional\c_page_marks_building_successive_pages\v!keep\fi]}
+
+\def\page_marks_synchronize_column#1#2#3#4% first last column box
+ {\ifnum#3=#1\relax
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!first,\v!column:\v!first][#4][]%
+ \orelse\ifnum#3=#2\relax
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!last, \v!column:\v!last ][#4][]%
+ \else
+ \strc_markings_synchronize[\number#3,\v!column:\number#3 ][#4][]%
+ \fi}
+
+% Page body building
+
+\newconditional\c_page_boxes_save_page_body
+\newbox \b_page_boxes_saved_page_body
+
+\def\page_boxes_constructed_page_body#1#2%
+ {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup
+ \boxmaxdepth\maxdimen % new
+ \dontcomplain
+ \page_marks_synchronize_page {#2}% we could consider doing this for \pagebox (needs testing)
+ \page_boxes_construct_content \pagebox{#1}{#2}%
+ \page_backgrounds_add_to_main \pagebox
+ \page_boxes_apply_offsets \pagebox
+ \page_info_add_to_box \pagebox
+ \ifcase\pageornamentstate
+ \page_backgrounds_add_to_paper \pagebox
+ \fi
+ \anch_positions_register_page \pagebox
+ \ifarrangingpages
+ \page_boxes_apply_shift_paper \pagebox % \v!paper
+ \else
+ \page_boxes_apply_clip_paper \pagebox
+ \page_marks_add_page \pagebox
+ \page_boxes_apply_replicate \pagebox
+ \page_boxes_apply_scale \pagebox
+ \page_boxes_apply_mirror_paper \pagebox
+ \page_boxes_apply_orientate_paper \pagebox
+ \page_marks_add_more \pagebox
+ \page_boxes_apply_center \pagebox
+ \page_backgrounds_add_to_print \pagebox
+ \page_boxes_apply_mirror_print \pagebox
+ \page_boxes_apply_orientate_print \pagebox
+ \page_boxes_apply_shift_print \pagebox % \v!page
+ \page_boxes_apply_offset \pagebox
+ \page_boxes_apply_negate_print \pagebox
+ \fi
+ \box\pagebox
+ \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi}
+
+\appendtoks
+ \restoreglobalbodyfont
+ \pickupattributes
+\to \everybeforepagebody
+
+% if we really need this ... we need to bypass \permanent
+
+% \ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed?
+%
+% \prependtoks
+% \let\nextbox\nestednextbox
+% \to \everybeforepagebody
+
+\def\page_boxes_constructed_page#1#2%
+ {\vpack\bgroup % intercept spurious spaces
+ \the\everybeforepagebody
+ \starttextproperties
+ \checkmarginblocks
+ \the\beforeeverypage
+ \normalexpanded{\global\beforepage\emptytoks\the\beforepage}%
+ \inpagebodytrue
+ \pagebodymode\plusone % todo: \plustwo when spread
+ \page_boxes_constructed_page_body#1#2%
+ \normalexpanded{\global\afterpage \emptytoks\the\afterpage }%
+ \the\aftereverypage
+ \resetpagebreak
+ \resetlayouttextlines % will go to \aftereverypage
+ \stoptextproperties
+ \the\everyafterpagebody
+ \egroup}
+
+\permanent\def\doifelsetopofpage
+ {\ifdim\pagegoal=\maxdimen
+ \expandafter\firstoftwoarguments
+ \orelse\ifdim\pagegoal=\vsize
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\aliased\let\doiftopofpageelse\doifelsetopofpage
+
+% %D Idea:
+%
+% \newinsert\thispageinsert % <- installinsertion
+%
+% \def\flushatthispage
+% {\bgroup
+% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
+% \hbox}
+%
+% \appendtoks
+% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
+% \to \everyshipout
+
+% not yet in i-* file
+
+\installcorenamespace{markedpage}
+
+% todo: just define at the lua end ... less hassle
+
+\permanent\tolerant\protected\def\markpage [#1]#*[#2]{\clf_markpage {#1}{#2}}
+\permanent \def\markedpages [#1]{\clf_markedpages {#1}} % expandable
+\permanent\protected \def\doifelsemarkedpage#1{\clf_doifelsemarkedpage{#1}}
+\permanent\protected \def\startmarkpages [#1]{\clf_startmarkpages {#1}}
+\permanent\protected \def\stopmarkpages {\clf_stopmarkpages }
+
+%D Experimental:
+
+\newconstant\c_page_force_strut_depth_trace_mode
+
+\installtextracker
+ {otr.forcestrutdepth}
+ {\c_page_force_strut_depth_trace_mode\plusone}
+ {\c_page_force_strut_depth_trace_mode\zerocount}
+
+\installoutputroutine\forcestrutdepth
+ {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode
+ \unvbox\normalpagebox}
+
+\installoutputroutine\forcestrutdepthplus % experimental
+ {\clf_forcestrutdepthplus\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode
+ \unvbox\normalpagebox}
+
+% maybe better:
+%
+% \installoutputroutine\doforcestrutdepth
+% {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode
+% \unvbox\normalpagebox}
+%
+% \protected\def\forcestrutdepth
+% {\par\ifvmode\ifinner\else\doforcestrutdepth\fi\fi}
+
+% Also experimental:
+
+\permanent\protected\def\doifelsependingpagecontent{\clf_doifelsependingpagecontent}
+% \permanent\protected\let\doifelsependingpagecontent\clf_doifelsependingpagecontent
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/page-inj.mkvi b/tex/context/base/mkiv/page-inj.mkvi
index b1a2913cf..f1b520f5e 100644
--- a/tex/context/base/mkiv/page-inj.mkvi
+++ b/tex/context/base/mkiv/page-inj.mkvi
@@ -149,7 +149,7 @@
\stopsetups
\startsetups[\??pageinjectionrenderings:\s!setup]
- \setups[\dummyparameter\c!setup]% kind of redundant but fits in
+ \setups[\dummyparameter\c!setups]% kind of redundant but fits in
\stopsetups
\startsetups[\??pageinjectionrenderings:\v!buffer]
diff --git a/tex/context/base/mkiv/page-lay.mkxl b/tex/context/base/mkiv/page-lay.mkxl
new file mode 100644
index 000000000..d24621e60
--- /dev/null
+++ b/tex/context/base/mkiv/page-lay.mkxl
@@ -0,0 +1,1625 @@
+%D \module
+%D [ file=page-lay,
+%D version=2000.10.20, % copied from main-001
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Layout Specification,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Layout Specification}
+
+%D Before you start wondering why some of the page related modules skip upward or
+%D left in order to place elements, you must realize that the reference point is the
+%D top left corner of the main typesetting area. One reason for this choice is that
+%D it suited some viewers that displayed page areas. Another reason is that margins,
+%D edges and top and bottom areas are kind of virtual, while the header, text and
+%D footer areas normally determine the text flow.
+
+\unprotect
+
+%D The dimensions related to layout areas are represented by real dimensions.
+
+\newdimen\paperheight \paperheight = 297mm
+\newdimen\paperwidth \paperwidth = 210mm
+\newdimen\paperoffset \paperoffset = \zeropoint
+\newdimen\paperbleed \paperbleed = \zeropoint
+\newdimen\spinewidth \spinewidth = \zeropoint
+
+\newdimen\printpaperheight \printpaperheight = \paperheight
+\newdimen\printpaperwidth \printpaperwidth = \paperwidth
+
+\newdimen\makeupheight % calculated
+\newdimen\makeupwidth % calculated
+
+\newdimen\textheight % calculated
+\newdimen\textwidth % calculated
+
+\newdimen\topspace \topspace = 2cm
+\newdimen\backspace \backspace = \topspace
+\newdimen\cutspace \cutspace = \zeropoint
+\newdimen\bottomspace \bottomspace = \zeropoint
+
+\newdimen\headerheight \headerheight = 2cm
+\newdimen\footerheight \footerheight = \headerheight
+
+\newdimen\topoffset \topoffset = \zeropoint
+\newdimen\backoffset \backoffset = \topoffset
+
+\newdimen\leftmarginwidth \leftmarginwidth = 3cm
+\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth
+
+\newdimen\leftedgewidth \leftedgewidth = 3cm
+\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth
+
+\newdimen\topheight \topheight = \zeropoint
+\newdimen\bottomheight \bottomheight = \topheight
+
+\newcount\layoutlines \layoutlines = \zerocount
+\newcount\layoutcolumns \layoutcolumns = \zerocount
+\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint
+\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint
+
+\newdimen\totaltextwidth
+
+%D The next series of dimensions are complemented by left and rights ones.
+
+\newdimen\margindistance
+\newdimen\edgedistance
+\newdimen\marginwidth
+\newdimen\edgewidth
+
+%D Because a distance does not really makes sense when there is no area, we use a
+%D zero distance in case there is no area.
+
+%D The horizontal distances are:
+
+\newdimen\leftedgedistance
+\newdimen\rightedgedistance
+\newdimen\leftmargindistance
+\newdimen\rightmargindistance
+
+%D The vertical distances are:
+
+\newdimen\topdistance
+\newdimen\headerdistance
+\newdimen\textdistance
+\newdimen\footerdistance
+\newdimen\bottomdistance
+
+\newdimen\textovershoot % available in pagebuilder
+
+%D We need to calculate the extra distances:
+
+\newdimen\naturalmarginwidth
+\newdimen\naturaledgewidth
+\newdimen\naturalmargindistance
+\newdimen\naturaledgedistance
+\newdimen\naturalleftedgedistance
+\newdimen\naturalrightedgedistance
+\newdimen\naturalleftmargindistance
+\newdimen\naturalrightmargindistance
+\newdimen\naturaltopdistance
+\newdimen\naturalheaderdistance
+\newdimen\naturaltextdistance
+\newdimen\naturalfooterdistance
+\newdimen\naturalbottomdistance
+
+%D Now we've come to the setup and definition commands.
+
+\installcorenamespace{layout}
+\installcorenamespace{layoutlocation}
+\installcorenamespace{layoutalternative}
+\installcorenamespace{layoutcolumn}
+\installcorenamespace{layoutmethod}
+
+\installswitchcommandhandler \??layout {layout} \??layout
+
+\appendtoks
+ \doifnothing{\directlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}%
+\to \everydefinelayout
+
+\appendtoks
+ \ifcase\layoutsetupmode
+ % can't happen
+ \or % \setuplayout[name][key=value]
+ \ifx\previouslayout\currentlayout
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \let\currentlayout\currentlayout
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \fi
+ \or % \setuplayout[key=value]
+ % we can inherit so we always synchronize
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \let\currentlayout\previouslayout
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \or % \setuplayout[name]
+ \ifx\currentlayout\v!reset
+ \let\currentlayout\empty
+ \fi
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \glet\currentlayout\currentlayout % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \or % \setuplayout (reverts to main layout)
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \glet\currentlayout\empty % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \fi
+\to \everysetuplayout
+
+\permanent\def\doifelselayoutdefined#1%
+ {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\aliased\let\doiflayoutdefinedelse\doifelselayoutdefined
+
+\permanent\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi}
+
+% \newconditional\reverselayout
+
+\def\page_layouts_set_dimensions
+ {\global\naturalmarginwidth \layoutparameter\c!margin
+ \global\naturaledgewidth \layoutparameter\c!edge
+ \global\naturalmargindistance \layoutparameter\c!margindistance
+ \global\naturaledgedistance \layoutparameter\c!edgedistance
+ \global\naturalleftedgedistance \layoutparameter\c!leftedgedistance
+ \global\naturalrightedgedistance \layoutparameter\c!rightedgedistance
+ \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance
+ \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance
+ \global\naturaltopdistance \layoutparameter\c!topdistance
+ \global\naturalheaderdistance \layoutparameter\c!headerdistance
+ \global\naturaltextdistance \layoutparameter\c!textdistance
+ \global\naturalfooterdistance \layoutparameter\c!footerdistance
+ \global\naturalbottomdistance \layoutparameter\c!bottomdistance
+ %
+ \global\marginwidth \naturalmarginwidth
+ \global\edgewidth \naturaledgewidth
+ \global\margindistance \naturalmargindistance
+ \global\edgedistance \naturaledgedistance
+ %
+ \global\leftedgedistance \layoutdistance\leftedgewidth \naturalleftedgedistance
+ \global\rightedgedistance \layoutdistance\rightedgewidth \naturalrightedgedistance
+ \global\leftmargindistance \layoutdistance\leftmarginwidth \naturalleftmargindistance
+ \global\rightmargindistance \layoutdistance\rightmarginwidth\naturalrightmargindistance
+ \global\topdistance \layoutdistance\topheight \naturaltopdistance
+ \global\headerdistance \layoutdistance\headerheight \naturalheaderdistance
+ \global\textdistance \naturaltextdistance
+ \global\footerdistance \layoutdistance\footerheight \naturalfooterdistance
+ \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance}
+
+\def\page_layouts_set_distances % local in \setreducedvsize
+ {\headerdistance\layoutdistance\headerheight\naturalheaderdistance
+ \footerdistance\layoutdistance\footerheight\naturalfooterdistance}
+
+% these are wrong in the running text, assumes some swapping, needs a cleanup
+
+\newtoks\extralayoutcalculations
+
+\def\page_layouts_calculate_extras
+ {\the\extralayoutcalculations}
+
+\newtoks\everyswapmargins % watch the order !
+
+\appendtoks
+ \enforced\swapcsvalues\leftmargindistance\rightmargindistance
+ \enforced\swapcsvalues\leftedgedistance \rightedgedistance
+ \enforced\swapcsvalues\leftmarginwidth \rightmarginwidth
+ \enforced\swapcsvalues\leftedgewidth \rightedgewidth
+ %
+ \enforced\swapcsvalues\leftmargintotal \rightmargintotal
+ \enforced\swapcsvalues\leftedgetotal \rightedgetotal
+ \enforced\swapcsvalues\leftsidetotal \rightsidetotal
+ \enforced\swapcsvalues\leftcombitotal \rightcombitotal
+ \enforced\swapcsvalues\innermargintotal \outermargintotal
+ \enforced\swapcsvalues\inneredgetotal \outeredgetotal
+ \enforced\swapcsvalues\innercombitotal \outercombitotal
+ \enforced\swapcsvalues\innersidetotal \outersidetotal
+\to \everyswapmargins
+
+%D The papersize macros have a long history and we don't want to change the commands
+%D so they keep looking a bit complex.
+
+%D \macros
+%D {definepapersize}
+%D
+%D Before we start calculating layout dimensions, we will first take care of paper
+%D sizes. The first argument can be either an assignment (for defaults) or an
+%D identifier, in which case the second argument is an assignment.
+%D
+%D \showsetup{definepapersize}
+%D
+%D Yet undocumented, let's see if it gets noticed.
+%D
+%D \starttyping
+%D \definepapersize[main] [A4] [A4]
+%D \definepapersize[extra][A4,landscape][A4,landscape]
+%D
+%D \starttext
+%D \setuppapersize[main]
+%D Page 1. \page
+%D Page 2. \page
+%D \setuppapersize[extra]
+%D Page 2 \page
+%D \setuppapersize[main]
+%D Page 3. \page
+%D Page 4. \page
+%D \adaptpapersize[extra]
+%D Page 5. \page
+%D Page 6. \page
+%D \stoptext
+%D \stoptyping
+%D
+%D \macros
+%D {setuppaper,setuppapersize}
+%D
+%D When setting up the papersize on which to typeset and print, we can also
+%D determine some more characteristics.
+%D
+%D \showsetup{setuppapersize}
+%D
+%D We keep track of these features with the following
+%D variables.
+
+\installcorenamespace{layouttarget}
+\installcorenamespace{layoutpaper}
+\installcorenamespace{layoutprint}
+\installcorenamespace{layoutcurrent}
+
+\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler
+
+\newconditional\c_page_target_paper_mirror
+\newconstant \c_page_target_paper_orientation
+\newconstant \c_page_target_paper_reverse
+\newconditional\c_page_target_paper_landscape
+\newconditional\c_page_target_paper_negate
+
+\newconditional\c_page_target_print_mirror
+\newconstant \c_page_target_print_orientation
+\newconstant \c_page_target_print_reverse
+\newconditional\c_page_target_print_landscape
+\newconditional\c_page_target_print_negate
+\newconditional\c_page_target_print_doublesided
+
+\let\v_page_target_left_fill \relax
+\let\v_page_target_right_fill \relax
+\let\v_page_target_top_fill \relax
+\let\v_page_target_bottom_fill\relax
+
+\let\papersize \empty
+\let\printpapersize\empty
+
+\def\v_page_target_top {\namedlayouttargetparameter\papersize\c!top }
+\def\v_page_target_bottom {\namedlayouttargetparameter\papersize\c!bottom}
+\def\v_page_target_left {\namedlayouttargetparameter\papersize\c!left }
+\def\v_page_target_right {\namedlayouttargetparameter\papersize\c!right }
+\def\v_page_target_method {\rootlayouttargetparameter \c!method}
+\def\v_page_target_scale {\rootlayouttargetparameter \c!scale }
+\def\v_page_target_nx {\numexpr\rootlayouttargetparameter \c!nx \relax}
+\def\v_page_target_ny {\numexpr\rootlayouttargetparameter \c!ny \relax}
+\def\v_page_target_dx {\dimexpr\rootlayouttargetparameter \c!dx \relax}
+\def\v_page_target_dy {\dimexpr\rootlayouttargetparameter \c!dy \relax}
+\def\v_page_target_width {\dimexpr\rootlayouttargetparameter \c!width \relax}
+\def\v_page_target_height {\dimexpr\rootlayouttargetparameter \c!height \relax}
+\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter \c!topspace \relax}
+\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter \c!backspace\relax}
+\def\v_page_target_offset {\dimexpr\rootlayouttargetparameter \c!offset \relax}
+
+\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax}
+
+%D Normally we will not use this command directly but for now it works out okay. In
+%D the future we might use more of the related commands.
+
+\setuplayouttarget
+ [% these are rather special
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!backspace=\zeropoint,
+ \c!width=\zeropoint,
+ \c!height=\zeropoint,
+ %
+ \c!method=\v!normal,
+ \c!option=\v!max,
+ \c!alternative=\v!normal,
+ %
+ \c!scale=1,
+ \c!offset=\zeropoint,
+ %
+ \c!top=,
+ \c!bottom=,
+ \c!left=,
+ \c!right=,
+ %
+ \c!location=]
+
+% \definepapersize[name][A4][A3]
+% \definepapersize[name][settings]
+
+\permanent\tolerant\protected\def\definepapersize[#1]#*[#2]#*[#3]%
+ {\edef\currentlayouttarget{#1}%
+ \ifx\currentlayouttarget\empty
+ % invalid target
+ \orelse\ifhastok={#2}%
+ \definelayouttarget[#1][#2]%
+ \else
+ \setevalue{\??layoutpaper#1}{#2}%
+ \ifparameter#3\or
+ \setevalue{\??layoutprint#1}{#3}%
+ \else
+ \setevalue{\??layoutprint#1}{#2}%
+ \fi
+ \fi}
+
+\appendtoks
+ \letvalue{\??layoutcurrent\currentlayouttarget}\relax
+\to \everydefinelayouttarget
+
+%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi}
+%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi}
+
+\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi}
+\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi}
+
+% \setuppaper [page=A4,paper=A3] % the k/v variant, changes the current page mapping
+% \setuppapersize[A4][a=b,c=d] % the k/v variant, changes nothing, just settings
+% \setuppapersize[A4][A3] % changes the current page mapping
+
+\let\page_paper_reinstate\relax
+\let\page_paper_restore \relax
+
+\permanent\tolerant\protected\def\setuppapersize[#1]#*[#2]%
+ {\ifarguments
+ \page_paper_restore
+ \or
+ \ifhastok={#1}%
+ \page_paper_setup_size_settings[#1]%
+ \orelse\ifhastok={#2}%
+ \page_paper_setup_size_settings_by_name[#1][#2]%
+ \else
+ \page_paper_setup_size_change_size[#1][#2]%
+ \fi
+ \fi}
+
+\protected\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size
+ {\let\currentlayouttarget\empty
+ \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
+ \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
+ \setupcurrentlayouttarget[#1]%
+ \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
+ \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
+ \ifx\m_layouttarget_paper_saved\m_layouttarget_paper
+ \ifx\m_layouttarget_print_saved\m_layouttarget_print
+ % we didn't change the size, maybe only sx or sy or so
+ \else
+ \page_paper_setup_size_settings_recalibrate
+ \fi
+ \else
+ \page_paper_setup_size_settings_recalibrate
+ \fi}
+
+\def\page_paper_setup_size_settings_recalibrate
+ {\ifx\m_layouttarget_paper\empty
+ % forget about it
+ \else
+ \ifx\m_layouttarget_print\empty
+ \let\m_layouttarget_print\m_layouttarget_paper
+ \fi
+ \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]%
+ \fi
+ \letlayouttargetparameter\c!page \papersize
+ \letlayouttargetparameter\c!paper\printpapersize}
+
+\protected\def\page_paper_setup_size_settings_by_name[#1][#2]%
+ {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}%
+ \setuplayouttarget[#2]}
+
+\protected\def\page_paper_setup_size_change_size[#1][#2]%
+ {\doifelsenothing{#2}
+ {\page_paper_set_current[#1][#1]}
+ {\page_paper_set_current[#1][#2]}}
+
+\permanent\let\setuppaper\page_paper_setup_size_settings
+
+\permanent\protected\def\adaptpapersize
+ {\glet\page_paper_reinstate\page_paper_restore
+ \setuppapersize}
+
+\appendtoks
+ \page_paper_reinstate
+ \glet\page_paper_reinstate\relax
+\to \everyaftershipout
+
+\protected\def\page_paper_set_restore#1#2%
+ {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}}
+
+\protected\def\page_paper_set_current[#1][#2]%
+ {\normalexpanded{\page_paper_set_current_indeed
+ [\page_paper_the_paper_size{#1}]%
+ [\page_paper_the_print_size{#2}]}}
+
+\protected\def\page_paper_reset_paper
+ {\global\setfalse\c_page_target_paper_landscape
+ \global\setfalse\c_page_target_paper_mirror
+ \global\setfalse\c_page_target_paper_negate
+ \global\c_page_target_paper_orientation\uprotationangle
+ \global\c_page_target_paper_reverse \uprotationangle}
+
+\protected\def\page_paper_reset_print
+ {\global\setfalse\c_page_target_print_landscape
+ \global\setfalse\c_page_target_print_mirror
+ \global\setfalse\c_page_target_print_negate
+ \global\c_page_target_print_orientation\uprotationangle
+ \global\c_page_target_print_reverse \uprotationangle}
+
+\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper
+\letvalue{\??layoutprint\v!reset}\page_paper_reset_print
+
+\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape}
+\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror}
+\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate}
+\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle
+ \global\c_page_target_paper_reverse \leftrotationangle}
+\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle
+ \global\c_page_target_paper_reverse \leftrotationangle}
+\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle
+ \global\c_page_target_paper_reverse \zerocount}
+\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle
+ \global\c_page_target_paper_reverse \rightrotationangle}
+
+\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape}
+\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror}
+\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate}
+\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle
+ \global\c_page_target_print_reverse \leftrotationangle}
+\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle
+ \global\c_page_target_print_reverse \leftrotationangle}
+\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle
+ \global\c_page_target_print_reverse \zerocount}
+\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle
+ \global\c_page_target_print_reverse \rightrotationangle}
+
+%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi}
+%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi}
+
+\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname}
+\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname}
+
+\protected\def\page_paper_identify_target#1%
+ {\ifcsname\??layoutcurrent#1\endcsname
+ \edef\currentlayouttarget{#1}%
+ \fi}
+
+\newdimen\d_page_minimum_paper_size \d_page_minimum_paper_size\luaexpr{math.pi}\onebasepoint
+
+\protected\def\page_paper_set_current_indeed[#1][#2]%
+ {\edef\m_page_asked_paper{#1}% can be the restores
+ \edef\m_page_asked_print{#2}%
+ %
+ \page_paper_set_restore\m_page_asked_paper\m_page_asked_print
+ %
+ % locate page target
+ \let\currentlayouttarget\empty
+ \page_paper_reset_paper
+ \processcommacommand[\m_page_asked_paper]\page_paper_identify_target
+ \ifx\currentlayouttarget\empty
+ \let\currentlayouttarget\currentpage
+ \fi
+ \glet\papersize\currentlayouttarget
+ \page_paper_reset_paper
+ \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option
+ \global\paperwidth \layouttargetparameter\c!width \relax
+ \global\paperheight\layouttargetparameter\c!height\relax
+ \ifdim\paperwidth<\d_page_minimum_paper_size
+ \global\paperwidth\d_page_minimum_paper_size
+ \fi
+ \ifdim\paperheight<\d_page_minimum_paper_size
+ \global\paperheight\d_page_minimum_paper_size
+ \fi
+ \ifconditional\c_page_target_paper_landscape
+ \enforced\global\swapcsvalues\paperwidth\paperheight
+ \fi
+ \ifinpagebody % local freeze
+ \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}%
+ \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}%
+ \fi
+ %
+ \page_paper_set_offsets
+ % locate paper target
+ \page_paper_reset_print
+ \processcommacommand[\m_page_asked_print]\page_paper_identify_target
+ \glet\printpapersize\currentlayouttarget
+ \page_paper_reset_print
+ \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option
+ \global\printpaperwidth \layouttargetparameter\c!width \relax
+ \global\printpaperheight\layouttargetparameter\c!height\relax
+ \ifdim\printpaperwidth<\onepoint
+ \global\printpaperwidth\paperwidth
+ \fi
+ \ifdim\printpaperheight<\onepoint
+ \global\printpaperheight\paperheight
+ \fi
+ \ifconditional\c_page_target_print_landscape
+ \enforced\global\swapcsvalues\printpaperwidth\printpaperheight
+ \fi
+ % this check can be confusing, so we've added the possibility
+ % to bypass this test: \setuppapersize[option=fit]
+ \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}%
+ \ifx\m_page_asked_option\v!max % \v!fit is
+ \begingroup
+ % we need to pre-swap else we get the wrong paper size
+ \ifnum\c_page_target_paper_orientation=\rightrotationangle
+ \enforced\swapcsvalues\paperwidth\paperheight
+ \orelse\ifnum\c_page_target_paper_orientation=\leftrotationangle
+ \enforced\swapcsvalues\paperwidth\paperheight
+ \fi
+ \ifnum\c_page_target_print_orientation=\rightrotationangle
+ \enforced\swapcsvalues\printpaperwidth\printpaperheight
+ \orelse\ifnum\c_page_target_print_orientation=\leftrotationangle
+ \enforced\swapcsvalues\printpaperwidth\printpaperheight
+ \fi
+ \ifdim\paperheight>\printpaperheight
+ \global\printpaperheight\paperheight
+ \writestatus\m!system{print height forced to paper height}%
+ \fi
+ \ifdim\paperwidth>\printpaperwidth
+ \global\printpaperwidth\paperwidth
+ \writestatus\m!system{print width forced to paper width}%
+ \fi
+ \endgroup
+ \fi
+ %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}%
+ \page_layouts_synchronize
+ % new but we assume \setuplayout
+ \scrn_canvas_synchronize_only}
+
+\ifdefined\scrn_canvas_synchronize_only \else
+ \let\scrn_canvas_synchronize_only\relax
+\fi
+
+\ifdefined\page_paper_set_offsets \else
+
+ \def\page_paper_set_offsets % will move
+ {\global\paperoffset\v_page_target_offset
+ \global\advance\paperwidth -2\paperoffset
+ \global\advance\paperheight-2\paperoffset}
+
+\fi
+
+\ifdefined\synchronizegridsnapping \else
+ \let\synchronizegridsnapping\relax
+\fi
+
+\let\p_page_layouts_width \empty
+\let\p_page_layouts_height\empty
+
+\def\page_layouts_synchronize
+ {\setups[\layoutparameter\c!preset]\relax
+ \global\leftmarginwidth \layoutparameter\c!leftmargin
+ \global\rightmarginwidth\layoutparameter\c!rightmargin
+ \global\leftedgewidth \layoutparameter\c!leftedge
+ \global\rightedgewidth \layoutparameter\c!rightedge
+ \global\headerheight \layoutparameter\c!header
+ \global\footerheight \layoutparameter\c!footer
+ \global\bottomheight \layoutparameter\c!bottom
+ \global\topheight \layoutparameter\c!top
+ \global\backspace \layoutparameter\c!backspace
+ \global\topspace \layoutparameter\c!topspace
+ \page_layouts_set_dimensions
+ \synchronizegridsnapping
+ \usesetupsparameter\layoutparameter % depends on gridsnapping !
+ \synchronizewhitespace
+ \synchronizeblank
+ \setupinterlinespace[\v!reset]% \synchronizegloballinespecs
+ \global\cutspace\layoutparameter\c!cutspace\relax
+ \edef\p_page_layouts_width{\layoutparameter\c!width}%
+ \ifx\p_page_layouts_width\v!middle
+ \ifzeropt\cutspace
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax
+ \orelse\ifx\p_page_layouts_width\v!fit
+ \ifzeropt\cutspace
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax
+ \scratchdimen\dimexpr\backspace
+ -\leftedgewidth -\leftedgedistance
+ -\leftmarginwidth-\leftmargindistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupwidth\dimexpr
+ -\rightmargindistance-\rightmarginwidth
+ -\rightedgedistance -\rightedgewidth
+ -\scratchdimen\relax
+ \else
+ \global\makeupwidth\p_page_layouts_width\relax
+ \ifzeropt\cutspace
+ \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax
+ % \else
+ % A kind of inconsistent specification, but used
+ % in for instance s-pre-19.tex; the cutspace is
+ % used only for determining some kind of right
+ % margin; don't use this in doublesided mode
+ \fi
+ \fi
+ \scratchdimen\layoutparameter\c!bottomspace\relax
+ %\ifzeropt\scratchdimen
+ % \scratchdimen\topspace
+ %\fi
+ \global\bottomspace\layoutparameter\c!bottomspace\relax
+ \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
+ \ifcase\layoutlines
+ \edef\p_page_layouts_height{\layoutparameter\c!height}%
+ \ifx\p_page_layouts_height\v!middle
+ \ifzeropt\bottomspace
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax
+ \orelse\ifx\p_page_layouts_height\v!fit
+ \ifzeropt\bottomspace
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\bottomspace\relax
+ \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax
+ \else
+ \global\makeupheight\layoutparameter\c!height\relax
+ \ifzeropt\bottomspace
+ \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
+ % \else
+ % inconsistent specification
+ \fi
+ \fi
+ \else
+ % beware, when the bodyfont changes (switched) this will change as well; implementing
+ % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set
+ % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we
+ % stick to the current method (after a night of experimenting ...2003/10/13)
+ \global\makeupheight\dimexpr
+ \layoutparameter\c!lines\lineheight-\strutheight+\topskip+
+ \headerdistance+\headerheight+\footerdistance+\footerheight\relax
+ \fi
+ \backoffset\layoutparameter\c!horoffset\relax
+ \topoffset \layoutparameter\c!veroffset\relax
+ \ifdim\makeupwidth<\onepoint
+ \global\makeupwidth\onepoint
+ \fi
+ \ifdim\makeupheight<\onepoint
+ \global\makeupheight\onepoint
+ \fi
+ % handy in page builder
+ \global\totaltextwidth\dimexpr
+ \leftedgetotal
+ +\leftmargintotal
+ +\makeupwidth
+ +\rightmargintotal
+ +\rightedgetotal
+ \relax
+ % \page_layouts_check_next % here ?
+ \page_layouts_check_direction
+ \page_layouts_calculate_extras
+ \page_target_check_centering
+ \calculatehsizes
+ \calculatevsizes
+ \page_layouts_check_pseudo_columns
+ \page_backgrounds_recalculate}
+
+\def\page_layouts_check_direction
+ {\edef\p_direction{\layoutparameter\c!direction}%
+ \ifx\p_direction\v!reverse
+ \enforced\global\swapcsvalues\naturalleftedgedistance \naturalrightedgedistance
+ \enforced\global\swapcsvalues\naturalleftmargindistance\naturalrightmargindistance
+ \enforced\global\swapcsvalues\leftedgedistance \rightedgedistance
+ \enforced\global\swapcsvalues\leftmargindistance \rightmargindistance
+ \enforced\global\swapcsvalues\leftmarginwidth \rightmarginwidth
+ \enforced\global\swapcsvalues\leftedgewidth \rightedgewidth
+ \enforced\global\swapcsvalues\backspace \cutspace
+ \expandafter\setsystemmode
+ \else
+ \expandafter\resetsystemmode
+ \fi{reverselayout}}
+
+\def\page_layouts_check_pseudo_columns
+ {\global\layoutcolumns\layoutparameter\c!columns
+ \global\layoutcolumndistance\layoutparameter\c!columndistance
+ \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
+ \ifnum\layoutcolumns>\plusone
+ \global\divide\layoutcolumnwidth\layoutcolumns
+ \dorecurse\layoutcolumns\page_layouts_check_pseudo_column
+ \fi}
+
+\def\page_layouts_check_pseudo_column
+ {\setxvalue{\??layoutcolumn\recurselevel}%
+ {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}}
+
+\letvalue{\??layoutcolumn0}\zeropoint
+
+\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs
+ {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname}
+
+\def\page_layouts_synchronize_at_start
+ {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check
+ \page_layouts_synchronize
+ \fi}
+
+\appendtoks
+ \page_layouts_synchronize_at_start % still needed?
+\to \everystarttext
+
+% document:
+%
+% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page]
+%
+% \startstandardmakeup[page=blank] ... \stopstandardmakeup
+
+\ifdefined\lastpage \else \let\lastpage\!!plusone \fi
+
+\def\page_layouts_change#1%
+ {%\writestatus\m!layouts{changing to layout #1}%
+ \xdef\currentlayout{#1}%
+ \page_layouts_synchronize}
+
+\let\changetolayout\page_layouts_change % also public
+
+\def\v_real_page_normal {\the\realpageno}
+\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax}
+
+\def\v_real_page_odd_or_even
+ {\ifodd\pagenoshift
+ \ifodd\realpageno\v!even\else\v!odd \fi
+ \else
+ \ifodd\realpageno\v!odd \else\v!even\fi
+ \fi}
+
+\let\v_real_page_current\v!current
+
+\def\v_real_page_named
+ {\ifnum\lastpage=\realpageno
+ \v!last
+ \orelse\ifnum\plusone=\realpageno
+ \v!first
+ \else
+ \__unknown__
+ \fi}
+
+\let\v_page_layouts_pre_check\relax
+
+\def\page_layouts_check_default_indeed#1%
+ {\edef\m_page_check{#1}
+ \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}%
+ \ifx\m_page_state\v!start
+ \glet\v_page_layouts_pre_check\currentlayout
+ \glet\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \orelse\ifx\m_page_state\v!repeat
+ \glet\v_page_layouts_pre_check\relax
+ \glet\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \fi}
+
+\def\page_layouts_check_revert
+ {\glet\currentlayout\v_page_layouts_pre_check
+ \glet\v_page_layouts_pre_check\relax
+ \page_layouts_synchronize}
+
+\def\page_layouts_check_default
+ {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_normal
+ \orelse\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_reverse
+ \orelse\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_named
+ \orelse\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_current
+ \orelse\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_odd_or_even
+ \orelse\ifx\v_page_layouts_pre_check\relax
+ % okay
+ \else
+ \page_layouts_check_revert
+ \fi}
+
+\permanent\protected\def\installlayoutmethod#1#2%
+ {\setgvalue{\??layoutmethod#1}{#2}}
+
+\installlayoutmethod\v!default{\page_layouts_check_default}
+\installlayoutmethod\v!normal {\page_layouts_check_default}
+
+% \def\page_layouts_check_next
+% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+% \layoutparameter\c!method
+% \else
+% \v!normal
+% \fi\endcsname}
+
+\def\page_layouts_check_next
+ {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+ \lastnamedcs
+ \else
+ \page_layouts_check_default
+ \fi}
+
+\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay
+
+% inheritance
+%
+% \definelayout
+% [test]
+% [width=12cm,
+% height=10cm]
+%
+% \definelayout
+% [more]
+% [test]
+% [height=12cm]
+%
+% testcase
+%
+% \setuppagenumbering[alternative=doublesided]
+%
+% \setuplayout [width=11cm]
+% \definelayout [odd] [backspace=1cm]
+% \definelayout [even] [backspace=4cm]
+% \definelayout [5] [backspace=5cm]
+% \definelayout [6] [backspace=5cm]
+% \definelayout [-2] [backspace=0cm,cutspace=0cm]
+% \definelayout [last] [backspace=0cm,cutspace=0cm]
+%
+% \checkcurrentlayout \showframe
+%
+% \starttext
+% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
+% \stoptext
+
+% Because we want to keep the set parameters as they are we use some
+% helpers to communicate between the several page building related
+% mechanism.
+
+\appendtoks \page_layouts_check_next \to \everystarttext
+\appendtoks \page_layouts_check_next \to \everyaftershipout
+
+\newconditional\c_page_layouts_location_is_set
+\newconditional\c_page_layouts_location_is_middle
+
+\def\page_layouts_location_reset % we start in the left top and mirror right pages
+ {\setfalse\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \relax
+ \let\v_page_target_right_fill \hss % ? \relax
+ \let\v_page_target_top_fill \relax
+ \let\v_page_target_bottom_fill\vss} % \relax}
+
+\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \hss
+ \let\v_page_target_right_fill \relax}
+\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \relax
+ \let\v_page_target_right_fill \hss}
+\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_top_fill \vss
+ \let\v_page_target_bottom_fill\relax}
+\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_top_fill \relax
+ \let\v_page_target_bottom_fill\vss}
+\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set
+ \settrue\c_page_layouts_location_is_middle
+ \let\v_page_target_left_fill \hss
+ \let\v_page_target_right_fill \hss
+ \let\v_page_target_top_fill \vss
+ \let\v_page_target_bottom_fill\vss}
+\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_
+ \setfalse\c_page_layouts_location_is_middle
+ \let\v_page_target_right_fill \hss
+ \let\v_page_target_bottom_fill\hss}
+\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided}
+\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided}
+
+\def\page_target_check_centering_indeed#1%
+ % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi}
+ {\begincsname\??layoutlocation#1\endcsname}
+
+\protected\def\page_target_check_centering
+ {\setfalse\c_page_target_print_doublesided
+ \page_layouts_location_reset
+ \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed}
+
+% installers
+
+\permanent\protected\def\installlayoutalternative#1#2%
+ {\setgvalue{\??layoutalternative#1}{#2}}
+
+\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box
+ {\setbox#1\vpack % was \vbox
+ {\offinterlineskip
+ \begingroup % needed ?
+ \uselayoutstyleandcolor\c!style\c!color
+ \offinterlineskip
+ \page_layouts_insert_elements % zero size
+ \endgroup
+ \page_insert_body#2#3}}% including footnotes
+
+\installlayoutalternative\v!default{\page_boxes_construct_content_default}
+\installlayoutalternative\v!normal {\page_boxes_construct_content_default}
+
+% \def\page_boxes_construct_content % targetbox flusher box
+% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+% \layoutparameter\c!alternative
+% \else
+% \v!normal
+% \fi\endcsname}
+
+\def\page_boxes_construct_content % targetbox flusher box
+ {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\page_boxes_construct_content_default
+ \fi}
+
+%D \macros
+%D {adaptlayout}
+
+\installcorenamespace{adaptlayout}
+\installcorenamespace{pageadaptations}
+
+\installsetuponlycommandhandler \??adaptlayout {adaptlayout}
+
+\newdimen\d_page_adepts_pushed_text_height
+\newdimen\d_page_adepts_pushed_footer_height
+\newdimen\d_page_adepts_height
+\newdimen\d_page_adapts_delta
+
+\permanent\protected\tolerant\def\adaptlayout[#1]#*[#2]%
+ {\ifparameter#2\or
+ \processcommalist[#1]{\page_adapts_layout_register{#2}}%
+ \page_adapts_check
+ \else
+ \page_adapts_layout_indeed{#1}%
+ \fi}
+
+\def\page_adapts_layout_register#1#2%
+ {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}}
+
+\let\p_adapts_height\zeropoint
+\let\p_adapts_lines \zerocount
+
+\def\page_adapts_layout_indeed#1%
+ {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]%
+ \page_adepts_push
+ \edef\p_adapts_height{\adaptlayoutparameter\c!height}%
+ \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}%
+ \ifx\p_adapts_height\v!max
+ \global\d_page_adepts_height\footerheight
+ \else
+ \global\d_page_adepts_height\dimexpr
+ \ifnum\p_adapts_lines=\zerocount
+ \p_adapts_height
+ \else
+ \p_adapts_lines\openlineheight
+ \fi
+ \relax
+ \ifdim\d_page_adepts_height>\footerheight
+ \global\d_page_adepts_height\footerheight
+ \fi
+ \fi
+ \global\advance\textheight \d_page_adepts_height
+ \global\advance\footerheight-\d_page_adepts_height
+ \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}%
+ % this will become a better one (do we need insert correction?)
+ \page_otr_command_set_vsize
+ %
+ \page_backgrounds_recalculate
+ \glet\page_adepts_push\relax
+ \glet\page_adepts_pop\page_adepts_pop_indeed}
+
+% \def\page_adapts_check
+% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
+%
+% \def\page_adapts_reset
+% {\ifcsname\??pageadaptations\the\realpageno\endcsname
+% \global\undefinevalue{\??pageadaptations\the\realpageno}%
+% \fi}
+
+\def\page_adapts_check
+ {\begincsname\??pageadaptations\the\realpageno\endcsname}
+
+\def\page_adapts_reset
+ {\ifcsname\??pageadaptations\the\realpageno\endcsname
+ \expandafter\glet\csname\??pageadaptations\the\realpageno\endcsname\relax
+ \fi}
+
+\def\page_adepts_push_indeed
+ {\global\d_page_adepts_pushed_text_height \textheight
+ \global\d_page_adepts_pushed_footer_height\footerheight}
+
+\def\page_adepts_pop_indeed
+ {\global\textheight \d_page_adepts_pushed_text_height
+ \global\footerheight\d_page_adepts_pushed_footer_height
+ \page_layouts_synchronize
+ \glet\page_adepts_push\page_adepts_push_indeed
+ \glet\page_adepts_pop\relax}
+
+\appendtoks \page_adapts_check \to \everystarttext
+\appendtoks \page_adapts_reset \to \everyshipout
+
+\let\page_adepts_pop \relax
+\let\page_adepts_push\page_adepts_push_indeed
+
+\protected\def\page_adapts_synchronize % used elsewhere
+ {\page_adepts_pop
+ \page_adapts_check}
+
+\def\page_adapts_status_info % used elsewhere
+ {\ifx\page_adepts_pop\relax \else
+ \space(adept: \the\d_page_adepts_height)\space
+ \fi
+ \the\realpageno}
+
+%D \macros
+%D {startlayout,stoplayout}
+
+\permanent\protected\def\startlayout[#1]%
+ {\page
+ \globalpushmacro\currentlayout
+ \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}}
+
+\permanent\protected\def\stoplayout
+ {\page
+ \globalpopmacro\currentlayout
+ \setuplayout[\currentlayout]}
+
+% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET
+
+\ifx\doifelselayoutsomeline\undefined % eventually defined in page-txt
+ \let\doifelselayoutsomeline\secondofthreearguments
+\fi
+
+\permanent\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\permanent\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+\permanent\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\permanent\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+
+\permanent\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances}
+\permanent\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances}
+
+\def\page_layouts_set_modes
+ {\ifzeropt\headerheight
+ \resetsystemmode\v!header
+ \else
+ \setsystemmode\v!header
+ \fi
+ \ifzeropt\footerheight
+ \resetsystemmode\v!footer
+ \else
+ \setsystemmode\v!footer
+ \fi}
+
+\permanent\protected\def\calculatevsizes % name will change
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing
+ \page_layouts_set_modes
+ \resetglobal
+ \page_otr_command_set_vsize}
+
+\permanent\protected\def\calculateglobalvsizes % name will change
+ {\global\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing
+ \page_layouts_set_modes
+ \page_otr_command_set_vsize}
+
+\permanent\protected\def\calculatereducedvsizes % name will change
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero}
+
+\newdimen\innermakeupwidth % special purpose
+\newdimen\innermakeupmargin % special purpose
+
+\newconditional\innermakeupcompensation \settrue\innermakeupcompensation
+
+\permanent\def\compensatedinnermakeupmargin
+ {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax}
+
+\permanent\protected\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth
+ {\textwidth\makeupwidth % which is a tricky but valid value
+ \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }%
+ \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}%
+ \ifx\m_currentlayout_text_width\empty \else
+ \textwidth\m_currentlayout_text_width % local
+ \fi
+ \global\innermakeupwidth\textwidth
+ \ifx\m_currentlayout_text_margin\empty
+ \global\innermakeupmargin\zeropoint
+ \else
+ \global\innermakeupmargin\m_currentlayout_text_margin\relax
+ \fi
+ \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax
+ \global\advance\innermakeupwidth-\scratchdimen
+ \advance\textwidth-\scratchdimen} % local
+
+\permanent\protected\def\calculatehsizes % name will change
+ {\freezetextwidth
+ \page_otr_command_set_hsize}
+
+%D When we start at an even page, we need to swap the layout differently. We cannot
+%D adapt the real page number, since it is used in cross referencing. The next
+%D switch is set when we start at an even page.
+
+% #single #left #right
+
+\permanent\def\doifelseoddpage
+ {\ifodd\pagenoshift
+ \expandafter\page_layouts_if_odd_else_yes
+ \else
+ \expandafter\page_layouts_if_odd_else_nop
+ \fi}
+
+\aliased\let\doifoddpageelse\doifelseoddpage
+
+\def\page_layouts_if_odd_else_yes
+ {\ifodd\realpageno
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_layouts_if_odd_else_nop
+ {\ifodd\realpageno
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\page_layouts_if_odd_else_again#1{\doifelseoddpage}
+
+\def\doifbothsidesoverruled
+ {\ifdoublesided
+ \expandafter\page_layouts_if_odd_else_again
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\doifbothsides% #1 #2 #3
+ {\ifdoublesided
+ \expandafter\page_layouts_if_both_sides
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\page_layouts_if_both_sides
+ {\ifsinglesided
+ \expandafter\firstofthreearguments
+ \else
+ \expandafter\page_layouts_if_odd_else_again
+ \fi}
+
+\newdimen\texthoffset
+
+\permanent\protected\def\settexthoffset % name will change
+ {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}
+
+\permanent\protected\def\goleftonpage % name will change (we could cache)
+ {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
+
+\permanent\def\doifelsemarginswap#1#2% protected?
+ {\doifbothsides{#1}{#1}{#2}}
+
+\aliased\let\doifmarginswapelse\doifelsemarginswap
+
+\def\swapmargins % name will change, frozen?
+ {\doifelsemarginswap\relax\doswapmargins}
+
+\def\doswapmargins % name will change, frozen?
+ {\let\swapmargins \relax % to prevent local swapping
+ \let\doswapmargins\relax % to prevent local swapping
+ \the\everyswapmargins}
+
+\permanent\def\rightorleftpageaction
+ {\ifdoublesided
+ \expandafter\page_layouts_right_or_left_page_action
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_layouts_right_or_left_page_action
+ {\ifsinglesided
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\doifelseoddpage
+ \fi}
+
+% swapping needs frozen
+
+\permanent\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\permanent\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\permanent\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\permanent\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\permanent\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\permanent\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\permanent\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\permanent\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\permanent\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace}
+\permanent\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace }
+
+\permanent\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax}
+\permanent\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax}
+\permanent\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax}
+\permanent\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax}
+
+\permanent\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax}
+\permanent\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax}
+\permanent\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax}
+\permanent\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax}
+
+\permanent\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax}
+\permanent\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax}
+\permanent\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax}
+\permanent\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax}
+
+\permanent\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax}
+\permanent\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax}
+\permanent\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax}
+\permanent\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax}
+
+%D \macros
+%D {startlocallayout}
+%D
+%D These macros should be used with care. They permit local layouts (as used in
+%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we
+%D have \type {\definelayout}, so this hack will disappear in future versions.
+
+\permanent\protected\def\startlocallayout
+ {\globalpushmacro\page_paper_restore
+ \globalpushmacro\currentlayout}
+
+\permanent\protected\def\stoplocallayout
+ {\globalpopmacro\currentlayout
+ \globalpopmacro\page_paper_restore
+ \page_paper_restore
+ \setuplayout[\currentlayout]\relax} % explicit !
+
+%D \macros
+%D {showprint, showframe, showlayout, showsetups}
+%D
+%D We predefine a couple of tracing macros.
+%D
+%D \showsetup{showprint}
+%D \showsetup{showframe}
+%D \showsetup{showlayout}
+%D \showsetup{showsetups}
+%D %showsetup{showmargins}
+%D %showsetup{showgrid}
+%D %showsetup{showusage}
+
+\fetchruntimecommand \showprint \f!page_run
+\fetchruntimecommand \showframe \f!page_run
+\fetchruntimecommand \showlayout \f!page_run
+\fetchruntimecommand \showsetups \f!page_run
+\fetchruntimecommand \showmargins \f!page_run
+\fetchruntimecommand \showgrid \f!page_run
+
+\glet\page_grids_add_to_box\gobbleoneargument
+\glet\page_grids_add_to_one\gobbleoneargument
+\glet\page_grids_add_to_mix\gobbleoneargument
+
+%D The default dimensions are quite old and will not change. The funny fractions
+%D were introduced when we went from fixed dimensions to relative ones. Since
+%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The
+%D asymmetrical layout is kind of handy for short quick||and||dirty stapled
+%D documents.
+%D
+%D Although valid, it is not a real good idea to use dimensions based on the \type
+%D {em} unit. First of all, since there are no fonts loaded yet, this dimension
+%D makes no sense, and second, you would loose track of values, since they could
+%D change while going to a new page, depending on the current font setting.
+
+\setuplayout
+ [ \c!topspace=.08417508418\paperheight, % 2.5cm
+ \c!top=\zeropoint,
+ \c!topdistance=\zeropoint,
+ \c!header=.06734006734\paperheight, % 2.0cm
+ \c!headerdistance=\zeropoint,
+ \c!height=.84175084175\paperheight, % 25.0cm
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=.06734006734\paperheight, % 2.0cm
+ \c!bottomdistance=\layoutparameter\c!topdistance,
+ \c!bottom=\zeropoint,
+ \c!backspace=.11904761905\paperwidth, % 2.5cm
+ \c!edge=\zeropoint,
+ \c!edgedistance=\layoutparameter\c!margindistance,
+ \c!margin=.12649983170\paperwidth, % snijwit-2*afstand
+ \c!margindistance=.02008341748\paperwidth, % 12.0pt
+ \c!leftedge=\layoutparameter\c!edge,
+ \c!leftedgedistance=\layoutparameter\c!edgedistance,
+ \c!leftmargin=\layoutparameter\c!margin,
+ \c!leftmargindistance=\layoutparameter\c!margindistance,
+ \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\
+ \c!rightmargindistance=\layoutparameter\c!margindistance,
+ \c!rightmargin=\layoutparameter\c!margin,
+ \c!rightedgedistance=\layoutparameter\c!edgedistance,
+ \c!rightedge=\layoutparameter\c!edge,
+ \c!veroffset=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!horoffset=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!textwidth=, % dangerous option -> centered / local
+ \c!textmargin=, % dangerous option -> both sides
+ \c!textdistance=\zeropoint, % shift down on grid
+ \c!style=,
+ \c!color=,
+ \c!marking=\v!off,
+ \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange)
+ \c!state=\v!start,
+ \c!scale=1,
+ \c!sx=1,
+ \c!sy=1,
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!grid=\v!no,
+ \c!direction=\v!normal,
+ \c!preset=,
+ \c!setups=\systemsetupsprefix\s!default,
+ \c!clipoffset=\zeropoint,
+ \c!lines=0,
+ \c!paper=, % for foxet
+ \c!page=, % for foxet
+ \c!columns=\plusone,
+ \c!columndistance=\zeropoint]
+
+%D First we define a whole range of (DIN) papersizes, of which the A-series makes
+%D most sense. We enable checking.
+
+\definepapersize [A0] [\c!width=841mm,\c!height=1189mm]
+\definepapersize [A1] [\c!width=594mm,\c!height=841mm]
+\definepapersize [A2] [\c!width=420mm,\c!height=594mm]
+\definepapersize [A3] [\c!width=297mm,\c!height=420mm]
+\definepapersize [A4] [\c!width=210mm,\c!height=297mm]
+\definepapersize [A5] [\c!width=148mm,\c!height=210mm]
+\definepapersize [A6] [\c!width=105mm,\c!height=148mm]
+\definepapersize [A7] [\c!width=74mm,\c!height=105mm]
+\definepapersize [A8] [\c!width=52mm,\c!height=74mm]
+\definepapersize [A9] [\c!width=37mm,\c!height=52mm]
+\definepapersize [A10] [\c!width=26mm,\c!height=37mm]
+
+\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm
+%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide
+
+\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm]
+\definepapersize [B1] [\c!width=707mm,\c!height=1000mm]
+\definepapersize [B2] [\c!width=500mm,\c!height=707mm]
+\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm]
+\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm]
+\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm]
+\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm]
+\definepapersize [B7] [\c!width=88mm,\c!height=125mm]
+\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm]
+\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm]
+\definepapersize [B10] [\c!width=31mm,\c!height=44mm]
+
+\definepapersize [C0] [\c!width=917mm,\c!height=1297mm]
+\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm]
+\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm]
+\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm]
+\definepapersize [C4] [\c!width=229mm,\c!height=324mm]
+\definepapersize [C5] [\c!width=162mm,\c!height=229mm]
+\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm]
+\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm]
+\definepapersize [C8] [\c!width=57mm,\c!height=81mm]
+\definepapersize [C9] [\c!width=40mm,\c!height=57mm]
+\definepapersize [C10] [\c!width=28mm,\c!height=40mm]
+
+%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the
+%D latest DIN specifications. Peter Rolf came up with these and a few more missing
+%D sizes. Watch out: spaces and slashes!
+
+\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm]
+\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm]
+\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm]
+
+%D Because there are no standardized screen sizes, we define a bunch of sizes with
+%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4}
+%D paper.
+
+\definepapersize [S3] [\c!width=300pt,\c!height=225pt]
+\definepapersize [S4] [\c!width=400pt,\c!height=300pt]
+\definepapersize [S5] [\c!width=500pt,\c!height=375pt]
+\definepapersize [S6] [\c!width=600pt,\c!height=450pt]
+\definepapersize [S8] [\c!width=800pt,\c!height=600pt]
+\definepapersize [SL] [\c!width=640pt,\c!height=400pt] % low
+\definepapersize [SM] [\c!width=720pt,\c!height=450pt] % medium
+\definepapersize [SW] [\c!width=800pt,\c!height=450pt] % wide
+\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt]
+\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt]
+\definepapersize [HD-] [\c!width=960pt,\c!height=540pt]
+
+%D These are handy too:
+
+\definepapersize [S33] [\c!width=300pt,\c!height=300pt]
+\definepapersize [S44] [\c!width=400pt,\c!height=400pt]
+\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
+\definepapersize [S66] [\c!width=600pt,\c!height=600pt]
+
+%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it
+%D does not hurt to have the paper size ready.
+
+\definepapersize [CD] [\c!width=120mm,\c!height=120mm]
+
+%D The next series is for our English speaking friends who decided to stick to non
+%D metric values. Thanks to Nelson Beebe for completing the inch based list.
+
+\definepapersize [letter] [\c!width=8.5in,\c!height=11in]
+\definepapersize [ledger] [\c!width=11in,\c!height=17in]
+\definepapersize [tabloid] [\c!width=17in,\c!height=11in]
+
+\definepapersize [legal] [\c!width=8.5in,\c!height=14in]
+\definepapersize [folio] [\c!width=8.5in,\c!height=13in]
+\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in]
+
+\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet
+\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets
+\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets
+
+%D The next set is for Tobias Burnus, who gave me the sizes.
+
+\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in]
+\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in]
+\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in]
+\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in]
+\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in]
+\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in]
+\definepapersize [check] [\c!width=8.58in,\c!height=3.88in]
+\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm]
+\definepapersize [E4] [\c!width=280mm,\c!height=400mm]
+
+%D The next three sets are supplied by Taco:
+
+\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm]
+\definepapersize [RA1] [\c!width=610mm,\c!height=860mm]
+\definepapersize [RA2] [\c!width=430mm,\c!height=610mm]
+\definepapersize [RA3] [\c!width=305mm,\c!height=430mm]
+\definepapersize [RA4] [\c!width=215mm,\c!height=305mm]
+
+%D ISO SRA (supplementary raw A) sizes:
+
+\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm]
+\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm]
+\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm]
+\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm]
+\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm]
+
+%D Swedish thesis formats:
+
+\definepapersize [G5] [\c!width=169mm,\c!height=239mm]
+\definepapersize [E5] [\c!width=155mm,\c!height=220mm]
+
+%D Industry invention:
+
+\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm]
+
+%D For Alan:
+
+\definepapersize [business] [\c!width=85mm,\c!height=55mm]
+\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in]
+
+%D We can now default to a reasonable size. We match the print paper size with the
+%D typeset paper size. This setting should come after the first layout specification
+%D (already done).
+
+% \definepapersize
+% [\v!default]
+% [ \c!width=\paperwidth,
+% \c!height=\paperheight]
+
+% \definepapersize
+% [samesized]
+% [ \c!width=\paperwidth,
+% \c!height=\paperheight]
+
+\setuppapersize
+ [\c!distance=1.5cm] % offset is already taken
+
+\definepapersize
+ [oversized]
+ [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [undersized]
+ [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [doublesized]
+ [ \c!width=\dimexpr \paperwidth \relax,
+ \c!height=\dimexpr2\paperheight\relax]
+
+\definepapersize
+ [doubleoversized]
+ [ \c!width=\dimexpr \paperwidth +\layouttargetparameter\c!distance\relax,
+ \c!height=\dimexpr2\paperheight+\layouttargetparameter\c!distance\relax]
+
+\definepapersize
+ [doublewide]
+ [ \c!width=\dimexpr2\paperwidth \relax,
+ \c!height=\dimexpr \paperheight\relax]
+
+% \setuppapersize
+% [A4][A4]
+
+\setuppapersize
+ [A4] % [samesized]
+
+%D A few goodies, first a full page layout:
+
+\definelayout
+ [\v!page]
+
+\setuplayout
+ [\v!page]
+ [\c!backspace=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!edge=\zeropoint,
+ \c!header=\zeropoint,
+ \c!footer=\zeropoint,
+ \c!top=\zeropoint,
+ \c!bottom=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!leftedge=\zeropoint,
+ \c!rightedge=\zeropoint,
+ \c!textdistance=\zeropoint,
+ \c!width=\v!middle,
+ \c!height=\v!middle,
+ \c!lines=0,
+ \c!grid=\v!no]
+
+%D A quick and dirty one:
+
+\definelayout
+ [\v!middle]
+ [\c!width=\v!middle,
+ \c!height=\v!middle]
+
+%D One for testing examples (5mm is often the non printable area):
+
+\definelayout
+ [\v!tight]
+
+\definelayout
+ [\v!tight]
+ [\v!page]
+ [\c!backspace=5mm,
+ \c!cutspace=5mm,
+ \c!topspace=5mm,
+ \c!bottomspace=5mm]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/page-lin.mkvi b/tex/context/base/mkiv/page-lin.mkvi
index ba3acef78..e355e3e60 100644
--- a/tex/context/base/mkiv/page-lin.mkvi
+++ b/tex/context/base/mkiv/page-lin.mkvi
@@ -53,7 +53,8 @@
\c_attr_linenumber\attributeunsetvalue
\to \everyinsidefloat
-\newcount \linenumber % not used
+\mutable\let\linenumber\!!zerocount
+
\newbox \b_page_lines_scratch
\newcount \c_page_lines_reference
\newconstant\c_page_lines_nesting
diff --git a/tex/context/base/mkiv/page-mcl.mkxl b/tex/context/base/mkiv/page-mcl.mkxl
index f90576cf6..6874e4fb2 100644
--- a/tex/context/base/mkiv/page-mcl.mkxl
+++ b/tex/context/base/mkiv/page-mcl.mkxl
@@ -98,7 +98,7 @@
\fi
-\unexpanded\def\page_mcl_command_set_hsize
+\protected\def\page_mcl_command_set_hsize
{\d_page_mcl_available_width\dimexpr
\makeupwidth
-\d_page_mcl_leftskip
@@ -112,7 +112,7 @@
\textwidth\d_page_mcl_used_width
\hsize\d_page_mcl_used_width}
-\unexpanded\def\page_mcl_set_n_of_lines#1%
+\protected\def\page_mcl_set_n_of_lines#1%
{\d_page_mcl_temp\dimexpr
+\textheight
\ifdim\d_page_mcl_preceding_height>\zeropoint -\d_page_mcl_preceding_height \fi
@@ -125,7 +125,7 @@
\fi \fi
\c_page_mcl_n_of_lines\noflines}
-\unexpanded\def\page_mcl_command_set_vsize
+\protected\def\page_mcl_command_set_vsize
{%%\page_one_command_set_vsize % indeed?
\page_mcl_set_n_of_lines\zeropoint
\d_page_mcl_temp\nofcolumns\dimexpr
@@ -135,7 +135,7 @@
\global\vsize \d_page_mcl_temp
\global\pagegoal\d_page_mcl_temp} % let's do it only here, reports maxdimen anyway
-\unexpanded\def\page_mcl_command_routine
+\protected\def\page_mcl_command_routine
{\ifcase\c_page_mcl_routine
\page_one_command_routine
\or
@@ -159,7 +159,7 @@
{\showmessage\m!columns3\empty
\page_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments
-\unexpanded\def\page_mcl_initialize_variables
+\protected\def\page_mcl_initialize_variables
{\reseteverypar % maybe still freeze ....
\dontcomplain
\settopskip
@@ -370,17 +370,12 @@
{%\global\setbox\currentcolumnbox\box\currentcolumnbox
\ht\currentcolumnbox\ht\firstcolumnbox}
-\unexpanded\def\startmulticolumns
- {\dosingleempty\page_mcl_start}
-
-\def\page_mcl_start[#1]%
+\tolerant\protected\def\startmulticolumns[#1]%
{\bgroup
\ifinsidecolumns
\page_mcl_start_nop
\else
- \iffirstargument
- \setupmulticolumns[#1]%
- \fi
+ \setupmulticolumns[#1]%
\nofcolumns\multicolumnsparameter\c!n\relax
\ifnum\nofcolumns>\plusone
\page_mcl_start_yes
@@ -390,16 +385,16 @@
\fi
\fi}
-\unexpanded\def\page_mcl_start_nop
- {\let\stopmulticolumns\page_mcl_stop_nop}
+\def\page_mcl_start_nop
+ {\enforced\let\stopmulticolumns\page_mcl_stop_nop}
-\unexpanded\def\page_mcl_stop_nop
+\permanent\protected\def\page_mcl_stop_nop
{\egroup}
-\unexpanded\def\page_mcl_start_yes
+\protected\def\page_mcl_start_yes
{\whitespace
\begingroup
- \let\stopmulticolumns\page_mcl_stop_indeed
+ \enforced\let\stopmulticolumns\page_mcl_stop_indeed
\global\insidecolumnstrue
\global\insidemulticolumnstrue
%
@@ -471,7 +466,7 @@
\page_otr_command_set_hsize
\page_otr_command_set_vsize}
-\unexpanded\def\page_mcl_stop_indeed
+\permanent\protected\def\page_mcl_stop_indeed
{\relax
\synchronizeoutput
\par
diff --git a/tex/context/base/mkiv/page-one.mkiv b/tex/context/base/mkiv/page-one.mkiv
index ada90eccf..f362a2fab 100644
--- a/tex/context/base/mkiv/page-one.mkiv
+++ b/tex/context/base/mkiv/page-one.mkiv
@@ -82,7 +82,12 @@
% 1 = partial page, 2 = whole page, 3 = partial page
-\setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day
+% We really need a setting! Todo, what key to use?
+
+\pushoverloadmode
+ \setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day
+ \overloaded\let\kindofpagetextareas\kindofpagetextareas
+\popoverloadmode
\def\page_one_registered_text_area_a % two arguments: (un)vbox n
{\ifconditional\c_page_areas_enabled
diff --git a/tex/context/base/mkiv/page-spr.mkxl b/tex/context/base/mkiv/page-spr.mkxl
new file mode 100644
index 000000000..877509e41
--- /dev/null
+++ b/tex/context/base/mkiv/page-spr.mkxl
@@ -0,0 +1,131 @@
+%D \module
+%D [ file=page-spr,
+%D version=2002.11.11,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Spreading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Page Macros / Spreading}
+
+% This module is experimental and not yet official!
+
+\unprotect
+
+\newbox \b_page_spread_content
+\newconditional\c_page_spread_busy
+\newconditional\c_page_spread_once % when true only one flush (writes etc)
+
+\permanent\overloaded\protected\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hpack
+ {\setlayoutcomponentattribute{\v!page:\v!text}%
+ \vpack \layoutcomponentboxattribute to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \page_otr_command_package_contents#2#3}}%
+ \dp#1\zeropoint
+ \ifconditional\c_page_spread_busy
+ \normalsettextpagecontent_spread{#1}%
+ \else
+ \normalsettextpagecontent_normal{#1}%
+ \fi}
+
+\def\normalsettextpagecontent_normal#1%
+ {\ifdim\wd#1=\makeupwidth\else
+ \setbox#1\hpack to \makeupwidth
+ {\hss\box#1\hss}% never change the \hss's
+ \fi}
+
+\def\normalsettextpagecontent_spread#1%
+ {\setbox#1\hpack to \makeupwidth
+ {\ifvoid\b_page_spread_content
+ \ifconditional\c_page_spread_once
+ \box#1%
+ \else
+ \global\setbox\b_page_spread_content\box#1%
+ \copy\b_page_spread_content
+ \fi
+ \hss % left page
+ \else
+ \hss % right page
+ \ifarrangingpages
+ % writes don't matter anyway
+ \else\ifconditional\c_page_spread_once
+ \global\setbox\b_page_spread_content\emptyhbox
+ \wd\b_page_spread_content\makeupwidth
+ \ht\b_page_spread_content\textheight
+ \else
+ % writes can interfere (todo: write stripper, but how about hyperlinks)
+ \fi \fi
+ \box\b_page_spread_content
+ \fi}}
+
+\protected\def\page_spread_flush
+ {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else
+ % this page will be discarded later
+ \emptyhbox \page
+ \fi \fi }
+
+\permanent\protected\def\startspread
+ {\ifdoublesided
+ \ifconditional\c_page_spread_busy
+ \doubleexpandafter\page_spread_start_nop
+ \else
+ \doubleexpandafter\page_spread_start_yes
+ \fi
+ \else
+ \expandafter\page_spread_start_nop
+ \fi}
+
+\let\stopspread\relax
+
+\protected\def\page_spread_start_yes
+ {\bgroup
+ \page[\v!left]%
+ %\setsystemmode{spread}%
+ \settrue\c_page_spread_busy
+ \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}%
+ \let\stopspread\page_spread_stop_yes}
+
+\protected\def\page_spread_stop_yes
+ {\kern\zeropoint
+ \page
+ \setuplayout[\c!textwidth=\textwidth]%
+ \page[\v!left]%
+ \egroup}
+
+\protected\def\page_spread_start_nop
+ {\bgroup
+ \let\stopspread\page_spread_stop_nop}
+
+\protected\def\page_spread_stop_nop
+ {\egroup}
+
+\protect \endinput
+
+% texexec --arr --pdf test
+%
+% \setuplayout[width=middle]
+% \setuppapersize[A4][A3,landscape]
+% \setuppagenumbering[alternative=doublesided]
+% \setuparranging[2UP]
+%
+% \starttext
+%
+% \dorecurse{3}{\input tufte }
+%
+% \startspread
+% \dorecurse{10}{\input tufte }
+% \stopspread
+%
+% \dorecurse{3}{\input tufte }
+%
+% \stoptext
diff --git a/tex/context/base/mkiv/page-txt.mklx b/tex/context/base/mkiv/page-txt.mklx
index ff582e561..6d9af76b0 100644
--- a/tex/context/base/mkiv/page-txt.mklx
+++ b/tex/context/base/mkiv/page-txt.mklx
@@ -77,11 +77,8 @@
\definelayoutelement[\v!footer:\v!edge] [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!bottom:\v!edge] [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
-\unexpanded\def\setuplayouttext
- {\dotripleempty\page_layouts_setup_text}
-
-\def\page_layouts_setup_text[#vertical][#horizontal][#settings]%
- {\ifthirdargument
+\permanent\tolerant\protected\def\setuplayouttext[#vertical]#spacer[#horizontal]#spacer[#settings]%
+ {\ifnum\lastarguments>\plustwo
\setuplayoutelement[#vertical:#horizontal][#settings]%
\else
\setuplayoutelement[#vertical][#horizontal]%
@@ -116,11 +113,11 @@
\ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi
\letgvalue{\??layouttextssynchronize#vertical}\currenttextstate}
-\unexpanded\def\setuptop {\dotripleempty\page_layouts_setup_text[\v!top ]}
-\unexpanded\def\setupheader{\dotripleempty\page_layouts_setup_text[\v!header]}
-\unexpanded\def\setuptext {\dotripleempty\page_layouts_setup_text[\v!text ]}
-\unexpanded\def\setupfooter{\dotripleempty\page_layouts_setup_text[\v!footer]}
-\unexpanded\def\setupbottom{\dotripleempty\page_layouts_setup_text[\v!bottom]}
+\permanent\protected\def\setuptop {\setuplayouttext[\v!top ]}
+\permanent\protected\def\setupheader{\setuplayouttext[\v!header]}
+\permanent\protected\def\setuptext {\setuplayouttext[\v!text ]}
+\permanent\protected\def\setupfooter{\setuplayouttext[\v!footer]}
+\permanent\protected\def\setupbottom{\setuplayouttext[\v!bottom]}
%D We inherit some settings:
@@ -143,11 +140,11 @@
%D \showsetup{noheaderandfooterlines}
%D \showsetup{notopandbottomlines}
-\unexpanded\def\noheaderandfooterlines
+\permanent\protected\def\noheaderandfooterlines
{\setuplayoutelement[\v!header][\c!state=\v!empty]%
\setuplayoutelement[\v!footer][\c!state=\v!empty]}
-\unexpanded\def\notopandbottomlines
+\permanent\protected\def\notopandbottomlines
{\setuplayoutelement[\v!top ][\c!state=\v!empty]%
\setuplayoutelement[\v!bottom][\c!state=\v!empty]}
@@ -169,59 +166,50 @@
%D someone uses the key|/|value interface these things have to be set explicitly as
%D part of the text.
-\unexpanded\def\setuptoptexts {\dosixtupleempty\page_layouts_setup_texts[\v!top ]}
-\unexpanded\def\setupheadertexts{\dosixtupleempty\page_layouts_setup_texts[\v!header]}
-\unexpanded\def\setuptexttexts {\dosixtupleempty\page_layouts_setup_texts[\v!text ]}
-\unexpanded\def\setupfootertexts{\dosixtupleempty\page_layouts_setup_texts[\v!footer]}
-\unexpanded\def\setupbottomtexts{\dosixtupleempty\page_layouts_setup_texts[\v!bottom]}
-
-\unexpanded\def\page_layouts_setup_text_six[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:#horizontal}%
- \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}%
- \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}}
-
-\unexpanded\def\page_layouts_setup_text_five[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:\v!text}%
- \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}%
- \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}}
-
-\unexpanded\def\page_layouts_setup_text_four[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:#horizontal}%
- \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}%
- \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}}
-
-\unexpanded\def\page_layouts_setup_text_three[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:\v!text}%
- \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}%
- \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}}
-
-\unexpanded\def\page_layouts_setup_text_two[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:\v!text}%
- \resetlayoutelementparameter\c!lefttext
- \resetlayoutelementparameter\c!righttext
- \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}}
-
-\unexpanded\def\page_layouts_setup_text_one[#vertical][#horizontal][#a][#b][#c][#d]%
- {\edef\currentlayoutelement{#vertical:\v!text}%
- \resetlayoutelementparameter\c!lefttext
- \resetlayoutelementparameter\c!righttext
- \resetlayoutelementparameter\c!middletext
- \edef\currentlayoutelement{#vertical:\v!margin}%
- \resetlayoutelementparameter\c!lefttext
- \resetlayoutelementparameter\c!righttext
- \resetlayoutelementparameter\c!middletext
- \edef\currentlayoutelement{#vertical:\v!edge}%
- \resetlayoutelementparameter\c!lefttext
- \resetlayoutelementparameter\c!righttext
- \resetlayoutelementparameter\c!middletext}
-
-\unexpanded\def\page_layouts_setup_texts
- {\ifsixthargument \expandafter\page_layouts_setup_text_six \orelse
- \iffifthargument \expandafter\page_layouts_setup_text_five \orelse
- \iffourthargument\expandafter\page_layouts_setup_text_four \orelse
- \ifthirdargument \expandafter\page_layouts_setup_text_three\orelse
- \ifsecondargument\expandafter\page_layouts_setup_text_two \else
- \expandafter\page_layouts_setup_text_one \fi}
+\permanent\protected\def\setuptoptexts {\setuptexts[\v!top ]}
+\permanent\protected\def\setupheadertexts{\setuptexts[\v!header]}
+\permanent\protected\def\setuptexttexts {\setuptexts[\v!text ]}
+\permanent\protected\def\setupfootertexts{\setuptexts[\v!footer]}
+\permanent\protected\def\setupbottomtexts{\setuptexts[\v!bottom]}
+
+\permanent\tolerant\protected\def\setuptexts[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]%
+ {\ifarguments
+ % there is always one
+ \or
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext
+ \edef\currentlayoutelement{#vertical:\v!margin}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext
+ \edef\currentlayoutelement{#vertical:\v!edge}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \resetlayoutelementparameter\c!middletext
+ \or
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}%
+ \or
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}%
+ \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}%
+ \or
+ \edef\currentlayoutelement{#vertical:#horizontal}%
+ \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}%
+ \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}%
+ \or
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}%
+ \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}%
+ \or
+ \edef\currentlayoutelement{#vertical:#horizontal}%
+ \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}%
+ \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}%
+ \fi}
%D Left and right texts are swapped on odd and even pages, but only when double
%D sided typesetting is enabled.
@@ -230,7 +218,7 @@
\let\m_page_layouts_element_content\empty
-\unexpanded\def\page_layouts_process_element_single#content%
+\protected\def\page_layouts_process_element_single#content%
{\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx
\ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
\lastnamedcs
@@ -240,12 +228,12 @@
{#content}%
\fi}
-\unexpanded\def\page_layouts_process_element_double#first#second%
+\protected\def\page_layouts_process_element_double#first#second%
{\doifelseoddpage
{\page_layouts_process_element_single{#first}}
{\page_layouts_process_element_single{#second}}}
-\unexpanded\def\page_layouts_process_element_indeed#style#color#width%
+\protected\def\page_layouts_process_element_indeed#style#color#width%
{\begingroup
\uselayoutelementstyleandcolor#style#color%
\begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
@@ -257,7 +245,6 @@
\endgroup}
\def\page_layouts_process_element_limited#content% are the {}{}{} still needed?
-% {\limitatetext{#content{}{}{}}\currentlayoutelementwidth\unknown}
{\limitated
left \currentlayoutelementwidth
text {#content}
@@ -294,7 +281,7 @@
\doifinset\v!footer\floatspecification{\setxvalue{\namedlayoutelementhash\v!footer\c!n}{1}}%
\to \everybeforeflushedpagefloat
-\unexpanded\def\page_layouts_place_text_line#vertical%
+\protected\def\page_layouts_place_text_line#vertical%
{\page_layouts_set_element_status#vertical\relax
\ifcsname\??layouttextsline\textlinestatus\endcsname
\expandafter\lastnamedcs
@@ -302,7 +289,7 @@
\expandafter\page_layouts_place_text_line_unknown
\fi#vertical}
-\unexpanded\def\doifelselayouttextline#vertical% shown or not
+\permanent\protected\def\doifelselayouttextline#vertical% shown or not
{\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
\ifx\currentlayoutelementstate\v!normal
\expandafter\firstoftwoarguments
@@ -312,7 +299,7 @@
\expandafter\secondoftwoarguments
\fi}
-\unexpanded\def\doifelselayoutsomeline#vertical% present or not
+\permanent\protected\def\doifelselayoutsomeline#vertical% present or not
{\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
\ifx\currentlayoutelementstate\v!none
\expandafter\secondoftwoarguments
@@ -377,7 +364,7 @@
%D The following macro has to be called after a page is flushed.
-\unexpanded\def\resetlayouttextlines % public
+\permanent\protected\def\resetlayouttextlines % public
{\begincsname\??layouttextsreset\v!top \endcsname
\begincsname\??layouttextsreset\v!header\endcsname
\begincsname\??layouttextsreset\v!text \endcsname
@@ -389,39 +376,36 @@
\global\setfalse\resyncaftertextline
\fi}
-\def\getspecificlayouttext#vertical#horizontal#what%
+\permanent\def\getspecificlayouttext#vertical#horizontal#what%
{\begincsname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname}
% \settext[header][text][middle][xxx][yyy]
-\unexpanded\def\settextcontent
- {\doquintupleempty\page_layouts_set_text_content}
-
-\def\page_layouts_set_text_content[#vertical][#horizontal][#one][#two][#three]% header text middle text/text
- {\iffifthargument
- \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}%
- {\page_layouts_process_element_double{#two}{#three}}%
- \orelse\iffourthargument
- \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}%
- {\page_layouts_process_element_double{#two}{#two}}%
- \orelse\ifthirdargument
+\permanent\tolerant\protected\def\settextcontent[#vertical]#spacer[#horizontal]#spacer[#one]#spacer[#two]#spacer[#three]% header text middle text/text
+ {\ifarguments\or\or\or % 3
\setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}%
{\page_layouts_process_element_double{#one}{#one}}%
+ \or % 4
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}%
+ {\page_layouts_process_element_double{#two}{#two}}%
+ \or % 5
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}%
+ {\page_layouts_process_element_double{#two}{#three}}%
\fi}
\let\currentlayoutelement\relax
-\unexpanded\def\resettextcontent
- {\dotripleempty\page_layouts_reset_text_content}
+%D This will be redefined, so no \type {\frozen} here!
-\def\page_layouts_reset_text_content[#vertical][#horizontal][#tag]% header text middle
- {\edef\currentlayoutelement{#vertical:#horizontal}%
- \ifthirdargument
- \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}%
- \orelse\ifsecondargument
+\permanent\tolerant\protected\def\resettextcontent[#vertical]#spacer[#horizontal]#spacer[#tag]% header text middle
+ {\ifarguments\or\or % 2
+ \edef\currentlayoutelement{#vertical:#horizontal}%
\resetlayoutelementparameter\c!lefttext
\resetlayoutelementparameter\c!middletext
\resetlayoutelementparameter\c!righttext
+ \or % 3
+ \edef\currentlayoutelement{#vertical:#horizontal}%
+ \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}%
\fi}
\letvalue{\??layouttextcontent\v!text:\c!middle}\c!middletext
@@ -718,20 +702,17 @@
%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
%D \stoptyping
-\unexpanded\def\definetext
- {\doseventupleempty\page_layouts_define_text}
-
-\def\page_layouts_define_text[#tag][#vertical][#horizontal][#a][#b][#c][#d]%
- {\ifseventhargument
- \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_six [#vertical][#horizontal][#a][#b][#c][#d]}%
- \orelse\ifsixthargument
- \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_five [#vertical][#horizontal][#a][#b][#c][]}%
- \orelse\iffifthargument
- \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_four [#vertical][#horizontal][#a][#b][][]}%
- \orelse\iffourthargument
- \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_three[#vertical][#horizontal][#a][][][]}%
- \else
- \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_two [#vertical][#horizontal][][][][]}%
+\permanent\tolerant\protected\def\definetext[#tag]#spacer[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]%
+ {\ifnum\lastarguments<\plusfour
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal]\relax}% 1, 2, 3
+ \orelse\ifarguments\or\or\or\or
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a]\relax}% 4
+ \or
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b]\relax}% 5
+ \or
+ \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c]\relax}% 6
+ \or
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c][#d]\relax}% 7
\fi}
%D A few more page breakers:
@@ -769,7 +750,7 @@
\let\m_page_layouts_page_number_location_h\relax
\let\m_page_layouts_page_number_location_x\relax
-\def\page_layouts_place_page_number % also elsewhere .. beware, not \unexpanded else
+\def\page_layouts_place_page_number % also elsewhere .. beware, not \protected else
{\strc_pagenumbers_place_location} % test below fails
\def\page_layouts_reset_page_number_location
@@ -817,7 +798,7 @@
\v!marginedge=>\let\m_page_layouts_page_number_location_h\v!text
\let\m_page_layouts_page_number_location_x\c!marginedgetext]}
-\unexpanded\def\strc_pagenumbers_set_location
+\protected\def\strc_pagenumbers_set_location
{\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}%
\ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location
% unchanged
@@ -949,10 +930,10 @@
%D The main text area has to be combined with some additional (tracing) information.
%D
%D This will be stored as normal and overloaded in page-lyr and later in page-spr we
-%D overload the the stored version .. evenatually i will clear up the experimental
+%D overload the the stored version .. eventually i will clear up the experimental
%D mess.
-\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded
+\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded
{\setbox#1\hpack to \makeupwidth
{\hss % so don't change this
\setlayoutcomponentattribute{\v!page:\v!text}%
diff --git a/tex/context/base/mkiv/phys-dim.mkiv b/tex/context/base/mkiv/phys-dim.mkiv
index f17861405..decc19bd3 100644
--- a/tex/context/base/mkiv/phys-dim.mkiv
+++ b/tex/context/base/mkiv/phys-dim.mkiv
@@ -175,8 +175,6 @@
%def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi}
\def\digitstimessymbol{\digitstextbinop\times}
-\unexpanded\def\mathplusminus{±} % will be in math-ini
-
\unexpanded\def\digitszeropadding {\hphantom{0}}
\unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}}
\unexpanded\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}}
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index da6c74b2e..ec36be89a 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -3500,7 +3500,7 @@ do
function publications.prerollcmdstring(str)
btxstring = str or ""
- tex.runtoks("t_btx_cmd")
+ tex.runlocal("t_btx_cmd")
return nodes.toutf(tex.getbox("b_btx_cmd").list) or str
end
diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv
index 996b6d3ca..12864aa6c 100644
--- a/tex/context/base/mkiv/publ-ini.mkiv
+++ b/tex/context/base/mkiv/publ-ini.mkiv
@@ -59,22 +59,24 @@
\startcontextdefinitioncode
-\def\s!btx {btx}
-
-\def\v!btxcite {btxcite}
-\def\v!btxlist {btxlist}
-\def\v!btxrendering {btxrendering}
-
-\def\s!btxset {btxset}
-\def\s!btxref {btxref}
-\def\s!btxint {btxint}
-\def\s!btxltx {btxltx}
-\def\s!btxrtx {btxrtx}
-\def\s!btxatx {btxatx}
-\def\s!btxbtx {btxbtx}
-\def\s!btxspc {btxspc}
-\def\s!btxlst {btxlst}
-\def\s!btxcom {btxcom}
+%D These are currently not interfaced.
+
+\definesystemconstant {btx}
+
+\definesystemconstant {btxset}
+\definesystemconstant {btxref}
+\definesystemconstant {btxint}
+\definesystemconstant {btxltx}
+\definesystemconstant {btxrtx}
+\definesystemconstant {btxatx}
+\definesystemconstant {btxbtx}
+\definesystemconstant {btxspc}
+\definesystemconstant {btxlst}
+\definesystemconstant {btxcom}
+
+\defineinterfacevariable {btxcite} {btxcite}
+\defineinterfacevariable {btxlist} {btxlist}
+\defineinterfacevariable {btxrendering} {btxrendering}
\definelabelclass[btxlabel][2]
diff --git a/tex/context/base/mkiv/scrn-but.mkvi b/tex/context/base/mkiv/scrn-but.mkvi
index 977b02acd..6c279dfc4 100644
--- a/tex/context/base/mkiv/scrn-but.mkvi
+++ b/tex/context/base/mkiv/scrn-but.mkvi
@@ -337,7 +337,7 @@
\let\scrn_menu_define_original\defineinteractionmenu
-\unexpanded\def\defineinteractionmenu
+\unexpanded\overloaded\def\defineinteractionmenu
{\dotripleempty\scrn_menu_define}
\def\scrn_menu_define[#tag][#category][#settings]% category reflects location, settings can be parent
diff --git a/tex/context/base/mkiv/scrn-wid.mkvi b/tex/context/base/mkiv/scrn-wid.mkvi
index ea77a7da3..d0b0fb006 100644
--- a/tex/context/base/mkiv/scrn-wid.mkvi
+++ b/tex/context/base/mkiv/scrn-wid.mkvi
@@ -605,7 +605,7 @@
{\iflocation
\clf_insertsoundclip
tag {#tag}%
- repeat {\directexternalsoundtrackparameter\c!option}%
+ repeat {\directexternalsoundtracksparameter\c!option}%
\relax
\fi}
diff --git a/tex/context/base/mkiv/spac-ali.mkiv b/tex/context/base/mkiv/spac-ali.mkiv
index ad1b118f8..7ed3416cc 100644
--- a/tex/context/base/mkiv/spac-ali.mkiv
+++ b/tex/context/base/mkiv/spac-ali.mkiv
@@ -797,7 +797,7 @@
\unexpanded\def\ibox
{\vbox\bgroup
\forgetall
- \let\\=\endgraf
+ \let\\\endgraf
\ifdoublesided\signalinnerrealign\fi
\doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left
\let\next}
@@ -805,7 +805,7 @@
\unexpanded\def\obox
{\vbox\bgroup
\forgetall
- \let\\=\endgraf
+ \let\\\endgraf
\ifdoublesided\signalouterrealign\fi
\doifelserightpage\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right
\let\next}
@@ -956,7 +956,7 @@
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
\setlocalhsize % new
- \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
+ \protected\def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
\dowithnextbox
{\hbox to \localhsize
{\ifcase\alignstrutmode\or\strut\fi
@@ -1036,7 +1036,7 @@
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
\setlocalhsize
- \def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient
+ \protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient
\dowithnextbox
{\hbox to \localhsize
{#1\hskip\ifdone#2\else#3\fi#4%
diff --git a/tex/context/base/mkiv/spac-ali.mkxl b/tex/context/base/mkiv/spac-ali.mkxl
index f4310dfc0..a41c99410 100644
--- a/tex/context/base/mkiv/spac-ali.mkxl
+++ b/tex/context/base/mkiv/spac-ali.mkxl
@@ -21,11 +21,11 @@
\registerctxluafile{spac-ali}{optimize}
-\chardef\normalizelinemodecode = "01
-\chardef\indentskipmodecode = "02
-\chardef\swaphangindentmodecode = "04
-\chardef\swapparskipmodecode = "08
-\chardef\breakafterdirmodecode = "10
+\immutable\chardef\normalizelinemodecode = "01
+\immutable\chardef\indentskipmodecode = "02
+\immutable\chardef\swaphangindentmodecode = "04
+\immutable\chardef\swapparskipmodecode = "08
+\immutable\chardef\breakafterdirmodecode = "10
\definesystemattribute[realign] [public] % might be combined with the next one
\definesystemattribute[alignstate][public] % will make a single attributes for several states
@@ -35,16 +35,16 @@
\c_attr_alignstate\attributeunsetvalue
\to \everyforgetall
-\unexpanded\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue}
-\unexpanded\def\signalinnerrealign{\clf_setrealign\plustwo}
-\unexpanded\def\signalouterrealign{\clf_setrealign\plusone}
+\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue}
+\permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo}
+\permanent\protected\def\signalouterrealign{\clf_setrealign\plusone}
\installcorenamespace{aligncommand}
\installcorenamespace{alignhorizontal}
\installcorenamespace{alignvertical}
-\installcorenamespace{alignmentnormalcache}
-\installcorenamespace{alignmentraggedcache}
+% \installcorenamespace{alignmentnormalcache}
+% \installcorenamespace{alignmentraggedcache}
% nasty hack:
@@ -54,8 +54,8 @@
\installcorenamespace{alignmentraggedcacheodd}
\installcorenamespace{alignmentraggedcacheeven}
-\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi}
-\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi}
+\immutable\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi}
+\immutable\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi}
\newtoks\everyresetalign % todo
@@ -65,48 +65,48 @@
\newconditional\displaylefttoright \settrue\displaylefttoright
\newconditional\inlinelefttoright \settrue\inlinelefttoright
-\unexpanded\def\lefttoright
+\permanent\protected\def\lefttoright
{\ifvmode
\spac_directions_lefttoright_vmode
\else
\spac_directions_lefttoright_hmode
\fi}
-\unexpanded\def\righttoleft
+\permanent\protected\def\righttoleft
{\ifvmode
\spac_directions_righttoleft_vmode
\else
\spac_directions_righttoleft_hmode
\fi}
-\unexpanded\def\spac_directions_lefttoright_vmode
+\protected\def\spac_directions_lefttoright_vmode
{\settrue\displaylefttoright
\settrue\inlinelefttoright
\textdirection\directionlefttoright
\pardirection \directionlefttoright}
-\unexpanded\def\spac_directions_righttoleft_vmode
+\protected\def\spac_directions_righttoleft_vmode
{\setfalse\displaylefttoright
\setfalse\inlinelefttoright
\textdirection\directionrighttoleft
\pardirection \directionrighttoleft}
-\unexpanded\def\spac_directions_lefttoright_hmode
+\protected\def\spac_directions_lefttoright_hmode
{\linedirection\directionlefttoright % linedir keeps subtype of skip
\settrue\inlinelefttoright}
-\unexpanded\def\spac_directions_righttoleft_hmode
+\protected\def\spac_directions_righttoleft_hmode
{\linedirection\directionrighttoleft % linedir keeps subtype of skip
\setfalse\inlinelefttoright}
-\unexpanded\def\synchronizelayoutdirection
+\permanent\protected\def\synchronizelayoutdirection
{\ifconditional\layoutlefttoright
\spac_directions_synchronize_lr
\else
\spac_directions_synchronize_rl
\fi}
-\unexpanded\def\synchronizedisplaydirection
+\permanent\protected\def\synchronizedisplaydirection
{\ifconditional\displaylefttoright
\spac_directions_synchronize_lr
\else
@@ -123,30 +123,30 @@
\textdirection\directionrighttoleft
\pardirection \directionrighttoleft}
-\unexpanded\def\synchronizeinlinedirection
+\permanent\protected\def\synchronizeinlinedirection
{% why not \linedirection here
\textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi}
-\unexpanded\def\checkedlefttoright
+\permanent\protected\def\checkedlefttoright
{\ifvmode
\spac_directions_lefttoright_vmode
\else
\spac_directions_lefttoright_hmode_checked
\fi}
-\unexpanded\def\checkedrighttoleft
+\permanent\protected\def\checkedrighttoleft
{\ifvmode
\spac_directions_righttoleft_vmode
\else
\spac_directions_righttoleft_hmode_checked
\fi}
-\unexpanded\def\spac_directions_lefttoright_hmode_checked
+\protected\def\spac_directions_lefttoright_hmode_checked
{\ifconditional\inlinelefttoright\else
\lefttoright
\fi}
-\unexpanded\def\spac_directions_righttoleft_hmode_checked
+\protected\def\spac_directions_righttoleft_hmode_checked
{\ifconditional\inlinelefttoright
\righttoleft
\fi}
@@ -156,10 +156,10 @@
\letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright
\letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft
-\unexpanded\def\usebidiparameter#1%
+\permanent\protected\def\usebidiparameter#1%
{\begincsname\??bidi#1\c!bidi\endcsname}
-\unexpanded\def\showdirections
+\permanent\protected\def\showdirections
{\dontleavehmode
\begingroup\infofont\textdirection\directionlefttoright[\space
layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space
@@ -167,20 +167,20 @@
inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space
]\endgroup}
-\unexpanded\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox
-\unexpanded\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox
-\unexpanded\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox
-\unexpanded\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox
-\unexpanded\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop
-\unexpanded\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop
+\permanent\protected\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox
+\permanent\protected\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox
+\permanent\protected\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox
+\permanent\protected\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox
+\permanent\protected\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop
+\permanent\protected\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop
-\unexpanded\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next}
-\unexpanded\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox
-\unexpanded\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop
+\permanent\protected\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next}
+\permanent\protected\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox
+\permanent\protected\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop
-\unexpanded\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi}
-\unexpanded\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi}
-\unexpanded\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi}
+\permanent\protected\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi}
+\permanent\protected\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi}
+\permanent\protected\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi}
% Tolerance and hyphenation
@@ -203,7 +203,7 @@
\def\spac_align_set_raggedness_middle{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi}
-\unexpanded\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered
+\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
@@ -215,37 +215,37 @@
% no need to do something as we're in \nohyphens
\fi}
-\unexpanded\def\spac_align_set_tolerant
+\protected\def\spac_align_set_tolerant
{\tolerance\c_spac_tolerance_normal}
-\unexpanded\def\spac_align_set_very_tolerant
+\protected\def\spac_align_set_very_tolerant
{\tolerance\c_spac_tolerance_extreme}
-\unexpanded\def\spac_align_set_stretch
+\protected\def\spac_align_set_stretch
{\emergencystretch\bodyfontsize}
-\unexpanded\def\spac_align_set_extreme_stretch
+\protected\def\spac_align_set_extreme_stretch
{\emergencystretch10\bodyfontsize}
% Vertical
\newconstant\c_spac_align_state_vertical
-\unexpanded\def\spac_align_set_vertical_none
- {\let\raggedtopcommand \relax
- \let\raggedbottomcommand\relax}
+\protected\def\spac_align_set_vertical_none
+ {\enforced\let\raggedtopcommand \relax
+ \enforced\let\raggedbottomcommand\relax}
-\unexpanded\def\spac_align_set_vertical_lohi
- {\let\raggedtopcommand \vfilll
- \let\raggedbottomcommand\vfilll}
+\protected\def\spac_align_set_vertical_lohi
+ {\enforced\let\raggedtopcommand \vfilll
+ \enforced\let\raggedbottomcommand\vfilll}
-\unexpanded\def\spac_align_set_vertical_low
- {\let\raggedtopcommand \vfilll
- \let\raggedbottomcommand\relax}
+\protected\def\spac_align_set_vertical_low
+ {\enforced\let\raggedtopcommand \vfilll
+ \enforced\let\raggedbottomcommand\relax}
-\unexpanded\def\spac_align_set_vertical_high
- {\let\raggedtopcommand \relax
- \let\raggedbottomcommand\vfilll}
+\protected\def\spac_align_set_vertical_high
+ {\enforced\let\raggedtopcommand \relax
+ \enforced\let\raggedbottomcommand\vfilll}
\def\spac_align_flush_vertical
{\ifcase\c_spac_align_state_vertical
@@ -289,7 +289,7 @@
% \s!plus ... slower than inline
-\unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips
+\permanent\protected\def\spac_align_set_horizontal_none % should also relax \updateraggedskips
{\raggedstatus \zerocount
\c_attr_alignstate\attributeunsetvalue
\leftskip \plusone\leftskip
@@ -301,7 +301,7 @@
\setfalse \raggedonelinerstate % now here
\let\updateraggedskips\relax} % no need for adaption
-\unexpanded\def\spac_align_set_horizontal_left
+\permanent\protected\def\spac_align_set_horizontal_left
{\setraggedness \spac_align_set_raggedness_left
\raggedstatus \plusone
\c_attr_alignstate\plusone
@@ -314,7 +314,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_center
+\permanent\protected\def\spac_align_set_horizontal_center
{\setraggedness \spac_align_set_raggedness_middle
\raggedstatus \plustwo
\c_attr_alignstate\plustwo
@@ -327,7 +327,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_right
+\permanent\protected\def\spac_align_set_horizontal_right
{\setraggedness \spac_align_set_raggedness_right
\raggedstatus \plusthree
\c_attr_alignstate\plusthree
@@ -340,7 +340,7 @@
%\parindent \parindent
\relax}
-\unexpanded\def\spac_align_set_horizontal_very_left
+\permanent\protected\def\spac_align_set_horizontal_very_left
{\raggedstatus \plusone
\c_attr_alignstate\plusone
\leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
@@ -352,7 +352,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_very_center
+\permanent\protected\def\spac_align_set_horizontal_very_center
{\raggedstatus \plustwo
\c_attr_alignstate\plustwo
\leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
@@ -364,7 +364,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_very_right
+\permanent\protected\def\spac_align_set_horizontal_very_right
{\raggedstatus \plusthree
\c_attr_alignstate\plusthree
\leftskip \plusone\leftskip \s!plus\zeropoint
@@ -376,7 +376,7 @@
%\parindent \parindent
\relax}
-\unexpanded\def\spac_align_set_horizontal_wide_center
+\permanent\protected\def\spac_align_set_horizontal_wide_center
{\setraggedness \spac_align_set_raggedness_middle
\raggedstatus \plustwo
\c_attr_alignstate\plustwo
@@ -389,7 +389,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_centered_last_line
+\permanent\protected\def\spac_align_set_horizontal_centered_last_line
{\raggedstatus \zerocount
\c_attr_alignstate\attributeunsetvalue
\leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax
@@ -401,7 +401,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_flushedright_last_line
+\permanent\protected\def\spac_align_set_horizontal_flushedright_last_line
{\raggedstatus \zerocount
\c_attr_alignstate\attributeunsetvalue
\leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax
@@ -413,7 +413,7 @@
\parindent \zeropoint
\relax}
-\unexpanded\def\spac_align_set_horizontal_right_tt % a plain command
+\permanent\protected\def\spac_align_set_horizontal_right_tt % a plain command
{\tttf % brrr
\raggedstatus \plusthree
\c_attr_alignstate\plusthree
@@ -426,7 +426,7 @@
%\parindent \parindent
\relax}
-\unexpanded\def\spac_align_set_horizontal_extra
+\permanent\protected\def\spac_align_set_horizontal_extra
{\xspaceskip\zeropoint\s!plus\v_spac_align_fill_amount_space\relax}
\def\spac_align_flush_horizontal
@@ -496,21 +496,21 @@
\newconstant\bottomraggednessmode % 0=ragged 1=normal/align 2=baseline
-\unexpanded\def\raggedbottom
+\permanent\protected\def\raggedbottom
{\bottomraggednessmode\zerocount
\settopskip}
-\unexpanded\def\alignbottom
+\permanent\protected\def\alignbottom
{\bottomraggednessmode\plusone
\settopskip}
-\unexpanded\def\baselinebottom
+\permanent\protected\def\baselinebottom
{\bottomraggednessmode\plustwo
\settopskip}
\let\normalbottom\alignbottom % downward compatible
-\unexpanded\def\setbottomalignmode#1%
+\permanent\protected\def\setbottomalignmode#1%
{\bottomraggednessmode#1%
\settopskip}
@@ -548,7 +548,7 @@
\let\updateraggedskips\relax
\def\spac_align_add_to_cache
- {\let\raggedbox\relax % why
+ {\enforced\let\raggedbox\relax % why
% we inherit hyphenation and tolerance
\t_spac_align_collected \emptytoks
\c_spac_align_state_broad \zerocount
@@ -582,7 +582,7 @@
% The local (key driven) setter:
-\unexpanded\def\spac_align_prepare#1% deferred
+\permanent\protected\def\spac_align_prepare#1% deferred
{\edef\m_spac_align_asked{#1}%
\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
\ifx\raggedcommand\relax
@@ -595,10 +595,7 @@
% The regular align setter:
-\unexpanded\def\setupalign
- {\dosingleempty\spac_align_setup}
-
-\def\spac_align_setup[#1]% immediate
+\permanent\tolerant\protected\def\setupalign[#1]% immediate
{\edef\m_spac_align_asked{#1}%
\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
\ifx\raggedcommand\relax
@@ -608,13 +605,13 @@
\fi
\raggedcommand}
-\unexpanded\def\usealignparameter#1% faster local variant
+\permanent\protected\def\usealignparameter#1% faster local variant
{\edef\m_spac_align_asked{#1\c!align}%
\ifx\m_spac_align_asked\empty\else
\spac_align_use_indeed
\fi}
-\unexpanded\def\dousealignparameter#1% faster local variant
+\permanent\protected\def\dousealignparameter#1% faster local variant
{\edef\m_spac_align_asked{#1}%
\ifx\m_spac_align_asked\empty\else
\spac_align_use_indeed
@@ -631,7 +628,7 @@
% experiment
-\unexpanded\def\spac_align_use_later#1%
+\protected\def\spac_align_use_later#1%
{\begingroup
\edef\m_spac_align_asked{#1}%
\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname
@@ -640,12 +637,12 @@
\fi
\endgroup}
-\unexpanded\def\spac_align_use_now#1%
+\protected\def\spac_align_use_now#1%
{\csname\??alignmentnormalcache#1\endcsname}
% Maybe we need something different in columns.
-\unexpanded\def\installalign#1#2% beware: commands must be unexpandable!
+\protected\def\installalign#1#2% beware: commands must be unexpandable!
{\ifcsname\??aligncommand#1\endcsname \else
\setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}%
\fi}
@@ -659,7 +656,7 @@
%
% this one could deal with both
%
-% \unexpanded\def\installalignoption#1#2%
+% \protected\def\installalignoption#1#2%
% {\ifcsname\??aligncommand#1\endcsname \else
% \setvalue{\??aligncommand#1}%
% {\spac_align_set_horizontal_none
@@ -759,7 +756,7 @@
\spac_align_flush_parfill_indeed{\number\c_spac_align_state_par_fill}%
\fi}
-\unexpanded\def\spac_align_flush_parfill_indeed#1%
+\protected\def\spac_align_flush_parfill_indeed#1%
{\parfillskip
#1\directhspaceamount\v!final
% plus \dimexpr\availablehsize-#1\directhspaceamount\v!final\relax
@@ -775,7 +772,7 @@
\setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plustwo }%
\to \t_spac_every_swap_align
-\unexpanded\def\enablereversealignment
+\permanent\protected\def\enablereversealignment
{\the\t_spac_every_swap_align
\t_spac_every_swap_align\emptytoks}
@@ -792,8 +789,7 @@
\let\centeredlastline \spac_align_set_horizontal_centered_last_line
\let\flushedrightlastline\spac_align_set_horizontal_flushedright_last_line
\let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command
-
-\let\forgetragged \spac_align_set_horizontal_none
+\let\forgetragged \spac_align_set_horizontal_none
\appendtoks
\spac_align_set_horizontal_none
@@ -801,18 +797,18 @@
% Box commands.
-\unexpanded\def\ibox
+\permanent\protected\def\ibox
{\vbox\bgroup
\forgetall
- \let\\=\endgraf
+ \enforced\let\\\endgraf
\ifdoublesided\signalinnerrealign\fi
\doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left
\let\next}
-\unexpanded\def\obox
+\permanent\protected\def\obox
{\vbox\bgroup
\forgetall
- \let\\=\endgraf
+ \enforced\let\\\endgraf
\ifdoublesided\signalouterrealign\fi
\doifelserightpage\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right
\let\next}
@@ -820,11 +816,11 @@
\let\raggedbox\relax
\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used)
- {\let\raggedbox\vbox
+ {\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)
- {\let\raggedbox\hbox
+ {\enforced\let\raggedbox\hbox
\processcommacommand[#1]\spac_align_set_ragged_hbox}
\def\spac_align_set_ragged_vbox#1%
@@ -839,35 +835,52 @@
\quitcommalist
\fi}
-\setvalue{\??alignvertical \v!left }{\let\raggedbox\lbox}
-\setvalue{\??alignvertical \v!right }{\let\raggedbox\rbox}
-\setvalue{\??alignvertical \v!middle }{\let\raggedbox\cbox}
-\setvalue{\??alignvertical \v!inner }{\let\raggedbox\ibox}
-\setvalue{\??alignvertical \v!outer }{\let\raggedbox\obox}
-\setvalue{\??alignvertical \v!flushleft }{\let\raggedbox\rbox}
-\setvalue{\??alignvertical \v!flushright}{\let\raggedbox\lbox}
-\setvalue{\??alignvertical \v!center }{\let\raggedbox\cbox}
-\setvalue{\??alignvertical \v!no }{\def\raggedbox{\vbox\bgroup\spac_align_set_horizontal_right\let\next=}]}
-
-% maybe \let's
-
-\setvalue{\??alignhorizontal\v!left }{\def\raggedbox{\doalignedline\v!left }}
-\setvalue{\??alignhorizontal\v!right }{\def\raggedbox{\doalignedline\v!right }}
-\setvalue{\??alignhorizontal\v!middle }{\def\raggedbox{\doalignedline\v!middle}}
-\setvalue{\??alignhorizontal\v!inner }{\def\raggedbox{\doalignedline\v!inner }}
-\setvalue{\??alignhorizontal\v!outer }{\def\raggedbox{\doalignedline\v!outer }}
-\setvalue{\??alignhorizontal\v!flushleft }{\def\raggedbox{\doalignedline\v!right }}
-\setvalue{\??alignhorizontal\v!flushright}{\def\raggedbox{\doalignedline\v!left }}
-\setvalue{\??alignhorizontal\v!center }{\def\raggedbox{\doalignedline\v!middle}}
+\permanent\protected\def\spac_align_vertical_left {\lbox}
+\permanent\protected\def\spac_align_vertical_right {\rbox}
+\permanent\protected\def\spac_align_vertical_middle {\cbox}
+\permanent\protected\def\spac_align_vertical_inner {\ibox}
+\permanent\protected\def\spac_align_vertical_outer {\obox}
+\permanent\protected\def\spac_align_vertical_flushleft {\rbox}
+\permanent\protected\def\spac_align_vertical_flushright{\lbox}
+\permanent\protected\def\spac_align_vertical_center {\cbox}
+\permanent\protected\def\spac_align_vertical_no {\vbox\bgroup\spac_align_set_horizontal_right\let\next=}
+
+\permanent\protected\def\spac_align_horizontal_left {\doalignedline\v!left}
+\permanent\protected\def\spac_align_horizontal_right {\doalignedline\v!right}
+\permanent\protected\def\spac_align_horizontal_middle {\doalignedline\v!middle}
+\permanent\protected\def\spac_align_horizontal_inner {\doalignedline\v!inner}
+\permanent\protected\def\spac_align_horizontal_outer {\doalignedline\v!outer}
+\permanent\protected\def\spac_align_horizontal_flushleft {\doalignedline\v!right}
+\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}
% The next one can be in use so we keep it around but oen should
% be aware of possible interference.
-\unexpanded\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall)
- {\unexpanded\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
+\permanent\protected\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall)
+ {\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
\updateraggedskips}
-\def\dosetraggedskips#1#2#3#4#5#6#7%
+\permanent\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
@@ -890,7 +903,7 @@
\expandafter\spac_show_par_data
\fi}
-\unexpanded\def\showpardata
+\permanent\protected\def\showpardata
{\edef\thepardata
{\hbox{font: \fontname\font}\endgraf
\spac_show_par_data
@@ -909,24 +922,24 @@
\endgroup
\let\showpardata\relax}
-\unexpanded\def\startshowpardata
+\permanent\protected\def\startshowpardata
{\begingroup
\showstruts
\tracingparagraphs\maxdimen
\appendtoksonce\showpardata\to\everypar}
-\unexpanded\def\stopshowpardata
+\permanent\protected\def\stopshowpardata
{\endgraf
\endgroup}
% Structure:
-\unexpanded\def\startalignment
+\protected\def\startalignment
{\par
\begingroup
\setupalign}
-\unexpanded\def\stopalignment
+\protected\def\stopalignment
{\par
\endgroup}
@@ -937,19 +950,19 @@
\newtoks \everyleftofalignedline
\newtoks \everyrightofalignedline
-\unexpanded\def\shiftalignedline#1#2#3#4% left, right, inner, outer
+\permanent\protected\def\shiftalignedline#1#2#3#4% left, right, inner, outer
{\rightorleftpageaction
{\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}%
\everyrightofalignedline{\hskip\dimexpr#2+#4\relax}}
{\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}%
\everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}}
-\def\doalignline#1#2% \\ == newline
+\permanent\def\doalignline#1#2% \\ == newline
{\noindentation % was \noindent
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
\setlocalhsize % new
- \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
+ \enforced\permanent\protected\def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
\dowithnextbox
{\hbox to \localhsize
{\ifcase\alignstrutmode\or\strut\fi
@@ -961,10 +974,10 @@
% plain commands
-\ifdefined\line \else \def\line {\hbox to\hsize} \fi
-\ifdefined\leftline \else \def\leftline #1{\line{#1\hss}} \fi
-\ifdefined\rightline \else \def\rightline #1{\line{\hss#1}} \fi
-\ifdefined\centerline \else \def\centerline#1{\line{\hss#1\hss}} \fi
+\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
% direct commands
@@ -978,36 +991,32 @@
\def\spac_align_wrapper_middle {\doalignline\hss \hss}
\def\spac_align_wrapper_handle#1%
- %{\csname\??alignwrapper\ifcsname\??alignwrapper#1\endcsname#1\else\v!middle\fi\endcsname}
{\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi}
-\unexpanded\def\spac_align_wrapper_start[#1]%
+\permanent\tolerant\protected\def\startlinealignment[#1]%
{\spac_align_wrapper_handle{#1}%
\bgroup\ignorespaces}
-\unexpanded\def\spac_align_wrapper_stop
+\protected\def\spac_align_wrapper_stop
{\removeunwantedspaces\egroup}
-\unexpanded\def\startlinealignment
- {\dosingleempty\spac_align_wrapper_start}
-
-\let\stoplinealignment\spac_align_wrapper_stop
+\permanent\let\stoplinealignment\spac_align_wrapper_stop
-\unexpanded\def\startleftaligned {\spac_align_wrapper_start[\v!left ]} \let\stopleftaligned \spac_align_wrapper_stop
-\unexpanded\def\startmiddlealigned{\spac_align_wrapper_start[\v!middle]} \let\stopmiddlealigned\spac_align_wrapper_stop
-\unexpanded\def\startrightaligned {\spac_align_wrapper_start[\v!right ]} \let\stoprightaligned \spac_align_wrapper_stop
-\unexpanded\def\startmaxaligned {\spac_align_wrapper_start[\v!max ]} \let\stopmaxaligned \spac_align_wrapper_stop
+\permanent\protected\def\startleftaligned {\startlinealignment[\v!left ]} \permanent\let\stopleftaligned \spac_align_wrapper_stop
+\permanent\protected\def\startmiddlealigned{\startlinealignment[\v!middle]} \permanent\let\stopmiddlealigned\spac_align_wrapper_stop
+\permanent\protected\def\startrightaligned {\startlinealignment[\v!right ]} \permanent\let\stoprightaligned \spac_align_wrapper_stop
+\permanent\protected\def\startmaxaligned {\startlinealignment[\v!max ]} \permanent\let\stopmaxaligned \spac_align_wrapper_stop
-\let\startmidaligned \startmiddlealigned \let\stopmidaligned \stopmiddlealigned
-\let\startcenteraligned\startmiddlealigned \let\stopcenteraligned\stopmiddlealigned
+\aliased\let\startmidaligned \startmiddlealigned \aliased\let\stopmidaligned \stopmiddlealigned
+\aliased\let\startcenteraligned\startmiddlealigned \aliased\let\stopcenteraligned\stopmiddlealigned
-\unexpanded\def\leftaligned {\spac_align_wrapper_handle\v!left }
-\unexpanded\def\middlealigned{\spac_align_wrapper_handle\v!middle}
-\unexpanded\def\rightaligned {\spac_align_wrapper_handle\v!right }
-\unexpanded\def\maxaligned {\spac_align_wrapper_handle\v!max }
+\permanent\protected\def\leftaligned {\spac_align_wrapper_handle\v!left }
+\permanent\protected\def\middlealigned{\spac_align_wrapper_handle\v!middle}
+\permanent\protected\def\rightaligned {\spac_align_wrapper_handle\v!right }
+\permanent\protected\def\maxaligned {\spac_align_wrapper_handle\v!max }
-\let\midaligned \middlealigned
-\let\centeraligned\middlealigned
+\aliased\let\midaligned \middlealigned
+\aliased\let\centeraligned\middlealigned
\installcorenamespace{alignline}
@@ -1019,17 +1028,17 @@
\letvalue{\??alignline\v!center }\midaligned
\letvalue{\??alignline\v!max }\maxaligned
-\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname}
+% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname}
%D Experimental (will be redone when floats are redone as it's real messy
%D now). It can also be made faster (if needed).
-\def\doxalignline#1#2#3#4#5#6%
+\permanent\protected\def\doxalignline#1#2#3#4#5#6%
{\noindentation % was \noindent
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
\setlocalhsize
- \def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient
+ \enforced\permanent\protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient
\dowithnextbox
{\hbox to \localhsize
{#1\hskip\ifdone#2\else#3\fi#4%
@@ -1042,7 +1051,7 @@
\endgroup}
\hbox}
-\def\doxcheckline % used for floats so multipass anyway
+\permanent\protected\def\doxcheckline % used for floats so multipass anyway
{\signalrightpage\doifelserightpage\donetrue\donefalse}
\setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss }
@@ -1059,11 +1068,9 @@
\setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax}
\setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
-\def\doalignedline#1% unchecked
- {\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
+\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
-\def\alignedline#1#2% setting default
- % {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname}
+\permanent\protected\def\alignedline#1#2% setting default
{\ifcsname\??alignline#1\endcsname
\expandafter\lastnamedcs
\else
@@ -1076,15 +1083,12 @@
%D We need to pick up a box (downward compatible in case \type {\bgroup}
%D is used (test suite index example).
-\unexpanded\def\wordright
- {\dosingleempty\spac_word_right}
-
-\def\spac_word_right[#1]%
+\permanent\tolerant\protected\def\wordright[#1]%
{\dowithnextbox
{\normalexpanded{\spac_word_right_indeed{#1}{\hpack{\thebox\nextbox}}}}
\hbox}
-\unexpanded\def\spac_word_right_indeed#1#2%
+\protected\def\spac_word_right_indeed#1#2%
{\registerparwrapper
{\v!word:\v!right}
{\begingroup
@@ -1119,13 +1123,13 @@
% Trick posted by WS on mailing list, generalized a bit. The bottom text only shows
% op when there is one line space available. We could add some extra space if needed.
-% \unexpanded\def\bottomword
+% v\protected\def\bottomword
% {\par
% \dowithnextbox
% {\leaders\box\nextbox\vfil\page}
% \vbox to \lineheight}
%
-% \unexpanded\def\bottomword
+% \permanent\protected\def\bottomword
% {\par
% \groupedcommand
% {\leaders
@@ -1141,9 +1145,9 @@
% todo: also handle \bgroup ... \egroup
-\unexpanded\def\spac_align_simple_left #1{{#1\hss}}
-\unexpanded\def\spac_align_simple_right #1{{\hss#1}}
-\unexpanded\def\spac_align_simple_middle#1{{\hss#1\hss}}
+\protected\def\spac_align_simple_left #1{{#1\hss}}
+\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
@@ -1161,7 +1165,7 @@
\letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left
\letvalue{\??alignsimplereverse\v!middle }\spac_align_simple_middle
-\unexpanded\def\simplealignedbox#1#2%
+\permanent\protected\def\simplealignedbox#1#2%
{\hbox \ifdim#1>\zeropoint to #1
\ifcsname\??alignsimple#2\endcsname
\doubleexpandafter\lastnamedcs
@@ -1170,7 +1174,7 @@
\fi
\fi}
-\unexpanded\def\simplealignedspreadbox#1#2%
+\permanent\protected\def\simplealignedspreadbox#1#2%
{\hbox \ifdim#1>\zeropoint spread #1
\ifcsname\??alignsimple#2\endcsname
\doubleexpandafter\lastnamedcs
@@ -1179,7 +1183,7 @@
\fi
\fi}
-\unexpanded\def\simplealignedboxplus#1#2#3%
+\permanent\protected\def\simplealignedboxplus#1#2#3%
{\hbox #3 \ifdim#1>\zeropoint to #1
\ifcsname\??alignsimple#2\endcsname
\doubleexpandafter\lastnamedcs
@@ -1190,7 +1194,7 @@
\newconditional\alignsimplelefttoright \settrue\alignsimplelefttoright
-\unexpanded\def\simplereversealignedbox#1#2%
+\permanent\protected\def\simplereversealignedbox#1#2%
{\hbox \ifdim#1>\zeropoint to #1
\ifcsname\??alignsimplereverse#2\endcsname
\doubleexpandafter\lastnamedcs
@@ -1199,7 +1203,7 @@
\fi
\fi}
-\unexpanded\def\simplereversealignedboxplus#1#2#3%
+\permanent\protected\def\simplereversealignedboxplus#1#2#3%
{\hbox #3 \ifdim#1>\zeropoint to #1
\ifcsname\??alignsimplereverse#2\endcsname
\doubleexpandafter\lastnamedcs
@@ -1220,16 +1224,13 @@
% \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss }
% \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax}
%
-% \unexpanded\def\spac_align_set_ss#1%
+% \protected\def\spac_align_set_ss#1%
% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname}
% Some obsolete (old) helpers:
-\unexpanded\def\definehbox
- {\dodoubleargument\spac_align_definehbox}
-
-\def\spac_align_definehbox[#1][#2]%
- {\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}}
+\permanent\tolerant\protected\def\definehbox[#1][#2]%
+ {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi}
%D Some direction related helpers:
@@ -1238,6 +1239,6 @@
\setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi}
\setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi}
-\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname}
+\permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname}
\protect \endinput
diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua
index ac04a4c8e..899d274b4 100644
--- a/tex/context/base/mkiv/spac-chr.lua
+++ b/tex/context/base/mkiv/spac-chr.lua
@@ -33,7 +33,7 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getattr = nuts.getattr
local setattr = nuts.setattr
-local getlang = nuts.getlang
+local getlanguage = nuts.getlanguage
local setchar = nuts.setchar
local setattrlist = nuts.setattrlist
local getfont = nuts.getfont
diff --git a/tex/context/base/mkiv/spac-chr.mkiv b/tex/context/base/mkiv/spac-chr.mkiv
index 43a725ae6..9113dc6a1 100644
--- a/tex/context/base/mkiv/spac-chr.mkiv
+++ b/tex/context/base/mkiv/spac-chr.mkiv
@@ -54,6 +54,8 @@
% Making them active is also not an option unless we do that in every
% catcode vector.
+\pushoverloadmode
+
% \nobreakspace {\begingroup\setalignstateattribute\normalUchar"00A0\endgroup} % 1 = left
\edef\nobreakspace {\normalUchar"00A0} % space
\edef\softhyphen {\normalUchar"00AD} % softhyohen
@@ -63,6 +65,9 @@
\let\ideographicspace \enquad
\let\ideographichalffillspace \emquad
+\unletfrozen\hairspace
+\unletfrozen\sixperemspace
+
\edef\twoperemspace {\normalUchar"2002} % quad/2
% % "2003 % quad == \quad == \hskip\emwidth
\edef\threeperemspace {\normalUchar"2004} % quad/3
@@ -88,6 +93,8 @@
\let\zwj \zerowidthjoiner
\let\nbsp \nobreakspace
+\popoverloadmode
+
\chardef\optionalspace"1F % will be space unless before punctuation
% Shortcuts:
diff --git a/tex/context/base/mkiv/spac-grd.mkxl b/tex/context/base/mkiv/spac-grd.mkxl
index 3e5030043..fbb02f50c 100644
--- a/tex/context/base/mkiv/spac-grd.mkxl
+++ b/tex/context/base/mkiv/spac-grd.mkxl
@@ -22,9 +22,9 @@
\installcorenamespace{lastnodepusher}
-\let\poplastnode\relax
+\permanent\let\poplastnode\relax
-\unexpanded\def\pushlastnode
+\permanent\protected\def\pushlastnode
{\csname\??lastnodepusher
\ifcsname\??lastnodepusher\the\lastnodetype\endcsname
\the\lastnodetype
@@ -34,19 +34,19 @@
\endcsname}
\setvalue{\??lastnodepusher\number\kernnodecode}%
- {\unexpanded\edef\poplastnode{\kern\the\lastkern\relax}%
+ {\enforced\permanent\protected\edef\poplastnode{\kern\the\lastkern\relax}%
\kern-\lastkern}
\setvalue{\??lastnodepusher\number\gluenodecode}%
- {\unexpanded\edef\poplastnode{\vskip\the\lastskip\relax}%
+ {\enforced\permanent\protected\edef\poplastnode{\vskip\the\lastskip\relax}%
\vskip-\lastskip}
\setvalue{\??lastnodepusher\number\penaltynodecode}%
- {\unexpanded\edef\poplastnode{\penalty\the\lastpenalty\relax}%
+ {\enforced\permanent\protected\edef\poplastnode{\penalty\the\lastpenalty\relax}%
\nobreak}
\setvalue{\??lastnodepusher\s!unknown}%
- {\let\poplastnode\relax}
+ {\enforced\permanent\let\poplastnode\relax}
%D Moved from supp-box:
@@ -115,9 +115,6 @@
\ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi
\ifdim\d_spac_lines_correction_after <\zeropoint\d_spac_lines_correction_after \zeropoint\fi}
-%unexpanded\def\dotopbaselinecorrection{\kern\d_spac_lines_correction_before}
-%unexpanded\def\dobotbaselinecorrection{\kern\d_spac_lines_correction_after }
-
% experiment, todo: proper mkiv mechanism
%
% \input ward \par
@@ -136,11 +133,11 @@
% to be redone:
-\unexpanded\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]}
-\unexpanded\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]}
+\permanent\protected\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]}
+\permanent\protected\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]}
-\def\showbaselinecorrection
- {\def\dobaselinecorrection % visualization is not watertight!
+\permanent\def\showbaselinecorrection
+ {\enforced\permanent\protected\def\dobaselinecorrection % visualization is not watertight!
{\bgroup
\ifdim\prevdepth>\zeropoint
\kern-\prevdepth
@@ -153,17 +150,15 @@
\ruledvpack{\box\scratchbox}%
\egroup
\prevdepth\strutdp}%
- \def\dotopbaselinecorrection
- {\hrule\s!height\d_spac_lines_correction_before}%
- \def\dobotbaselinecorrection
- {\hrule\s!height\d_spac_lines_correction_after}}
+ \enforced\permanent\protected\def\dotopbaselinecorrection{\hrule\s!height\d_spac_lines_correction_before}%
+ \enforced\permanent\protected\def\dobotbaselinecorrection{\hrule\s!height\d_spac_lines_correction_after }}
% \def\dobaselinecorrection % beware, this one is redefined below
% {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi
% \kern\strutdp
% \prevdepth\strutdp}
-\def\baselinecorrection
+\permanent\protected\def\baselinecorrection
{\endgraf
\ifvmode
\ifdim\prevdepth<\maxdimen
@@ -177,7 +172,7 @@
\fi
\fi}
-\def\pagebaselinecorrection
+\permanent\protected\def\pagebaselinecorrection
{\ifdim\pagegoal<\maxdimen
\ifdim\pagetotal>\lineheight % or \topskip
\scratchdimen\pagetotal
@@ -188,35 +183,35 @@
\fi
\fi}
-\unexpanded\def\startbaselinecorrection
+\permanent\protected\def\startbaselinecorrection
{\bgroup
- \let\stopbaselinecorrection\egroup
+ \enforced\let\stopbaselinecorrection\egroup
\ifcase\baselinecorrectionmode
\or % normal
\baselinecorrection
\ifvmode
\setbox\scratchbox\vbox\bgroup\ignorespaces
- \let\stopbaselinecorrection\donormalstopbaselinecorrection
+ \enforced\let\stopbaselinecorrection\donormalstopbaselinecorrection
\fi
\or % off
\or % force
\baselinecorrection
\ifvmode
\setbox\scratchbox\vbox\bgroup\ignorespaces
- \let\stopbaselinecorrection\doforcedstopbaselinecorrection
+ \enforced\let\stopbaselinecorrection\doforcedstopbaselinecorrection
\fi
\fi}
-\let\stopbaselinecorrection\relax
+\permanent\let\stopbaselinecorrection\relax
-\def\donormalstopbaselinecorrection % I have to check columns yet.
+\permanent\protected\def\donormalstopbaselinecorrection % I have to check columns yet.
{\egroup
\topbaselinecorrection
\box\scratchbox
\botbaselinecorrection
\egroup}
-\def\doforcedstopbaselinecorrection % I have to check columns yet.
+\permanent\protected\def\doforcedstopbaselinecorrection % I have to check columns yet.
{\egroup
\forcedtopbaselinecorrection
\box\scratchbox
@@ -229,31 +224,31 @@
\setnewconstant\baselinecorrectionmode\plusone
-\def\onbaselinecorrection {\baselinecorrectionmode\plusone }
-\def\offbaselinecorrection {\baselinecorrectionmode\plustwo }
-\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree}
+\permanent\protected\def\onbaselinecorrection {\baselinecorrectionmode\plusone }
+\permanent\protected\def\offbaselinecorrection {\baselinecorrectionmode\plustwo }
+\permanent\protected\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree}
%D \macros
%D {topbaselinecorrection,botbaselinecorrection}
%D
%D The actual top and bottom corrections are implemented as:
-\def\topbaselinecorrection
+\permanent\protected\def\topbaselinecorrection
{\ifvmode \ifdim\pagegoal<\maxdimen
\forcedtopbaselinecorrection
\fi \fi}
-\def\forcedtopbaselinecorrection
- {\ifvmode
- \bgroup
- \spac_lines_initialize_corrections
- \whitespace % no longer ok
- \nointerlineskip
- \dotopbaselinecorrection
- \egroup
- \fi}
+% \permanent\protected\def\forcedtopbaselinecorrection
+% {\ifvmode
+% \bgroup
+% \spac_lines_initialize_corrections
+% \whitespace % no longer ok
+% \nointerlineskip
+% \dotopbaselinecorrection
+% \egroup
+% \fi}
-\def\botbaselinecorrection
+\permanent\protected\def\botbaselinecorrection
{\ifvmode
\bgroup
\spac_lines_initialize_corrections
@@ -263,8 +258,6 @@
\egroup
\fi}
-\let\forcedbotbaselinecorrection\botbaselinecorrection
-
% nointerlineskip
%
% startpacked
@@ -272,17 +265,17 @@
% \startlinecorrection \framed{test} \stoplinecorrection
% \stoppacked
-\def\forcedtopbaselinecorrection
+\permanent\protected\def\forcedtopbaselinecorrection
{\ifvmode
\bgroup
\spac_lines_initialize_corrections
\vspacing[\v!white]
-% \nointerlineskip %
+ %\nointerlineskip %
\dotopbaselinecorrection
\egroup
-\fi}
+ \fi}
-\def\dobaselinecorrection
+\permanent\protected\def\dobaselinecorrection
{\ifdim\prevdepth>\zeropoint
\vspacing[\the\dimexpr-\prevdepth+\strutdp\relax]%
\else
@@ -290,17 +283,17 @@
\fi
\prevdepth\strutdp}
-% \def\dobaselinecorrection
+% \permanent\protected\def\dobaselinecorrection
% {\scratchdimen\dimexpr\ifdim\prevdepth>\zeropoint-\prevdepth+\fi\strutdp\relax
% \vspacing[\the\scratchdimen]%
% \prevdepth\strutdp}
%
% some day:
%
-% \def\dobaselinecorrection
+% \permanent\protected\def\dobaselinecorrection
% {\clf_checkstrutdepth\strutdp}
%
-% \def\baselinecorrection
+% \permanent\protected\def\baselinecorrection
% {\endgraf
% \ifvmode
% \ifdim\prevdepth<\maxdimen
@@ -321,7 +314,7 @@
%D For the moment only with placefloats (should work in mvl and boxes):
-\unexpanded\def\checkprevdepth
+\permanent\protected\def\checkprevdepth
{\endgraf
\ifvmode
\ifdim\prevdepth<\maxdimen
@@ -335,18 +328,22 @@
\let\normalstartbaselinecorrection\startbaselinecorrection
-\unexpanded\def\startbaselinecorrection
+\pushoverloadmode
+
+\permanent\protected\def\startbaselinecorrection
{\ifgridsnapping
\snaptogrid[\v!normal]\vbox\bgroup
- \let\stopbaselinecorrection\egroup
+ \enforced\let\stopbaselinecorrection\egroup
\else
\normalstartbaselinecorrection
\fi}
+\popoverloadmode
+
% This is new (and experimental) and might replace some of the above. beware it doesn't always work
% out well, e.g. when used grouped and such (e.g. before display math doesn't work out well).
-% \unexpanded\def\fakenextstrutline
+% \permanent\protected\def\fakenextstrutline
% {\par
% \begingroup
% \reseteverypar
@@ -355,7 +352,7 @@
% \vskip-\struttotal
% \endgroup}
-% \unexpanded\def\fakenextstrutline
+% \permanent\protected\def\fakenextstrutline
% {\par
% \begingroup
% \reseteverypar
@@ -366,7 +363,7 @@
% \fi
% \endgroup}
-% \unexpanded\def\fakenextstrutline
+% \permanent\protected\def\fakenextstrutline
% {\par
% \begingroup
% \reseteverypar
diff --git a/tex/context/base/mkiv/spac-hor.mkxl b/tex/context/base/mkiv/spac-hor.mkxl
index e0fb9e407..c394308f3 100644
--- a/tex/context/base/mkiv/spac-hor.mkxl
+++ b/tex/context/base/mkiv/spac-hor.mkxl
@@ -30,16 +30,13 @@
%D After a blank or comparable situation (left side floats) we
%D need to check if the next paragraph has to be indented.
-\unexpanded\def\presetindentation
+\permanent\protected\def\presetindentation
{\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}}
-\unexpanded\def\setupindenting
+\permanent\protected\def\setupindenting
{\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size}
-% \unexpanded\def\spac_indentation_setup_size
-% {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}}
-
-\unexpanded\def\spac_indentation_setup_size
+\protected\def\spac_indentation_setup_size
{\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}%
\ifzeropt\parindent\else
\parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand
@@ -74,7 +71,7 @@
\def\spac_indentation_set_everypar
{\everypar{\checkindentation}}
-\unexpanded\def\useindentingparameter#1% faster local variant
+\permanent\protected\def\useindentingparameter#1% faster local variant
{\edef\m_spac_indentation_options{#1\c!indenting}%
\ifx\m_spac_indentation_options\empty \else
\spac_indentation_setup_indeed
@@ -105,37 +102,8 @@
\installcorenamespace {indentingpreset}
-\unexpanded\def\defineindenting
- {\dodoubleargument\spac_indenting_define}
-
-\def\spac_indenting_define[#1][#2]% todo: mixes
- {\setevalue{\??indentingpreset#1}{#2}}
-
-% \def\spac_indentation_apply_step_one_nested#1%
-% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one}
-%
-% \def\spac_indentation_apply_step_two_nested#1%
-% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two}
-%
-% \def\spac_indentation_apply_step_one#1%
-% {\ifcsname\??indentingpreset#1\endcsname
-% \spac_indentation_apply_step_one_nested{#1}%
-% \orelse\ifcsname\??indentingmethod#1\endcsname
-% % case two
-% \else
-% \edef\v_spac_indentation_current{#1}% single entry in list
-% \let\normalindentation\v_spac_indentation_current
-% \spac_indentation_setup_size
-% \fi}
-%
-% \def\spac_indentation_apply_step_two#1%
-% {\ifcsname\??indentingpreset#1\endcsname
-% \spac_indentation_apply_step_two_nested{#1}%
-% \orelse\ifcsname\??indentingmethod#1\endcsname
-% \lastnamedcs
-% \else
-% % case one
-% \fi}
+\permanent\tolerant\protected\def\defineindenting[#1]#*[#2]% todo: mixes
+ {\ifarguments\else\setevalue{\??indentingpreset#1}{#2}\fi}
\def\spac_indentation_apply_step_one_nested
{\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one}
@@ -163,14 +131,14 @@
% case one
\fi}
-\unexpanded\def\indenting % kind of obsolete
+\permanent\protected\def\indenting % kind of obsolete
{\doifelsenextoptionalcs\spac_indentation_setup_options\relax}
% use \noindentation to suppress next indentation
\installcorenamespace{indentingmethod}
-\unexpanded\def\installindentingmethod#1#2%
+\permanent\protected\def\installindentingmethod#1#2%
{\setvalue{\??indentingmethod#1}{#2}}
\installindentingmethod \v!no {\parindent\zeropoint}
@@ -203,8 +171,8 @@
\zeropoint
\fi\relax}
-\unexpanded\def\noindenting{\indenting[\v!no, \v!next ]}
-\unexpanded\def\doindenting{\indenting[\v!yes,\v!first]}
+\permanent\protected\def\noindenting{\indenting[\v!no, \v!next ]}
+\permanent\protected\def\doindenting{\indenting[\v!yes,\v!first]}
%D Here come the handlers (still rather messy ... we need states).
@@ -260,19 +228,19 @@
{\spac_indentation_remove
\glet\checkindentation\spac_indentation_do_indeed}
-\def\spac_indentation_variant_no % made global
+\permanent\protected\def\spac_indentation_variant_no % made global
{\ifinpagebody \else
%\global\indentationfalse
\glet\checkindentation\spac_indentation_no_next_check
\fi}
-\def\nonoindentation % bv bij floats
+\permanent\protected\def\nonoindentation % bv bij floats
{\ifinpagebody \else
%\global\indentationtrue
\glet\checkindentation\spac_indentation_do_indeed
\fi}
-\def\spac_indentation_variant_force
+\permanent\protected\def\spac_indentation_variant_force
{\ifvmode \ifzeropt\parindent \else
% was : \hskip\parindent
% can be: \indent
@@ -296,27 +264,27 @@
\let\noindentation\spac_indentation_variant_no % public
\let\doindentation\spac_indentation_variant_yes % public
-\def\dontrechecknextindentation % public (in macros)
- {\glet\dorechecknextindentation\relax}
+\permanent\protected\def\dontrechecknextindentation % public (in macros)
+ {\global\enforced\let\dorechecknextindentation\relax}
-\let\dorechecknextindentation\relax % public (in macros)
+\let\dorechecknextindentation\relax % public (in macros)
-\unexpanded\def\spac_indentation_check_next_indentation
- {\glet\dorechecknextindentation\relax
+\permanent\protected\protected\def\spac_indentation_check_next_indentation
+ {\global\enforced\let\dorechecknextindentation\relax
\doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par
\def\spac_indentation_variant_auto
- {\glet\dorechecknextindentation\spac_indentation_check_next_indentation}
+ {\global\enforced\let\dorechecknextindentation\spac_indentation_check_next_indentation}
%D This one sets up the local indentation behaviour (i.e. either or not
%D a next paragraph will be indented).
\installcorenamespace{indentnext}
-\unexpanded\def\checknextindentation[#1]%
+\permanent\protected\def\checknextindentation[#1]%
{\begincsname\??indentnext#1\endcsname}
-\unexpanded\def\useindentnextparameter#1% new, the more efficient variant
+\permanent\protected\def\useindentnextparameter#1% new, the more efficient variant
{\edef\p_indentnext{#1\c!indentnext}%
\ifx\p_indentnext\empty\else
\begincsname\??indentnext\p_indentnext\endcsname
@@ -366,7 +334,7 @@
% maybe an everyforgetparindent
-\unexpanded\def\forgetparindent
+\permanent\protected\def\forgetparindent
{\settrue\c_spac_indentation_indent_first % recently added
\d_spac_indentation_par\zeropoint
\parindent\zeropoint
@@ -376,7 +344,7 @@
\forgetparindent
\to \everyforgetall
-\unexpanded\def\forgethorizontalstretch
+\permanent\protected\def\forgethorizontalstretch
{\emergencystretch\zeropoint}
\appendtoks
@@ -385,7 +353,7 @@
%D Helper:
-\unexpanded\def\softbreak
+\permanent\protected\def\softbreak
{\relax\ifhmode\hskip\parfillskip\break\fi}
%D \macros
@@ -413,27 +381,33 @@
\sfcode`\?3000 \sfcode`\!3000
\sfcode`\:2000 \sfcode`\;1500 }
-\unexpanded\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand}
-\unexpanded\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}}
-\unexpanded\def\nonfrenchspacing{\spac_spacecodes_set_stretch}
+\permanent\protected\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand}
+\permanent\protected\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}}
+\permanent\protected\def\nonfrenchspacing{\spac_spacecodes_set_stretch}
-\unexpanded\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}}
+\permanent\protected\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}}
\installspacingmethod \empty {} % keep values
\installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere
\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation
\installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation
-\unexpanded\def\setupspacing
- {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop}
-
-\def\spac_spacecodes_setup_yes[#1]%
- {\begincsname\??spacecodemethod#1\endcsname
+%% \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
+ \fi
\updateraggedskips}
-\def\spac_spacecodes_setup_nop
- {\updateraggedskips}
-
%D Here's a tweak .. if needed one can configure it in the configuration
%D so that initialization happens more efficient.
%D
@@ -453,7 +427,7 @@
% This is not needed, as \updateraggedskips is taking care of it:
-\let\synchronizespacecodes\spac_spacecodes_setup_nop % \relax
+\permanent\protected\def\synchronizespacecodes{\updateraggedskips}
% \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par
% \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par
@@ -476,16 +450,20 @@
%D from now on we treat it as a normal space and not as a space with \type
%D {sfcode} 1000.
-\unexpanded\def\specialspaceprimitive
+\permanent\protected\def\specialspaceprimitive
{\begingroup
% so, no fancy extra spacing after: foo i.e.\ bar
\nonfrenchspacing\normalspaceprimitive
\endgroup}
-\unexpanded\def\normalnotobeyedspace
+\permanent\protected\def\normalnotobeyedspace
{\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing)
-\let\ =\normalnotobeyedspace
+\pushoverloadmode
+
+\overloaded\let\ =\normalnotobeyedspace % so we redefine the primitive!
+
+\popoverloadmode
% Because I strip spaces at the end of lines (in the editor) we need a bit of
% a trick to define slash+newline, so \space and \<newline> are the same
@@ -508,27 +486,27 @@
% \ruledhbox spread 10pt {\frenchspacing xx dr.~X}
% \ruledhbox spread 10pt {\nonfrenchspacing xx dr.~X}
-\unexpanded\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math
+\permanent\protected\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math
\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later
- \def\space { }
-\unexpanded\def\removelastspace{\ifhmode\unskip\fi}
-\unexpanded\def\nospace {\removelastspace\ignorespaces}
+% \def\space { }
+\permanent\protected\def\removelastspace{\ifhmode\unskip\fi}
+\permanent\protected\def\nospace {\removelastspace\ignorespaces}
\ifdefined\nospaces
- \unexpanded\def\nospacing{\normalnospaces\plusone}
- \unexpanded\def\dospacing{\normalnospaces\zerocount}
+ \permanent\protected\def\nospacing{\normalnospaces\plusone}
+ \permanent\protected\def\dospacing{\normalnospaces\zerocount}
\else
- \unexpanded\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint}
- \unexpanded\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what
+ \permanent\protected\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint}
+ \permanent\protected\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what
\fi
\ifdefined\softhyphen \else
\let\softhyphen\explicitdiscretionary
\fi
-\cldcontext{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"}
+\cldcontext{"\string\\protected\string\\def\string\\\string\n{\string\\space}"}
%cldcontext{"\string\\let\string\\\string\n=\string\\space"}
% in tables we need:
@@ -537,31 +515,31 @@
%
% but, since not all fonts have .5em digits:
-\unexpanded\def\fixedspace
+\permanent\protected\def\fixedspace
{\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox
\hskip\wd\scratchbox\relax}
-\unexpanded\def\fixedspaces
+\permanent\protected\def\fixedspaces
{\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace
- \let~\fixedspace} % we need to renew it
+ \enforced\let~\fixedspace} % we need to renew it
\appendtoks
- \let~\space
- \let\ \space
+ \enforced\let~\space
+ \enforced\let\ \space
\to \everysimplifycommands
\newsignal\s_spac_keep_unwanted_space
% \parindentmode\plusone
-\unexpanded\def\keepunwantedspaces
+\permanent\protected\def\keepunwantedspaces
{\ifhmode
\ifdim\lastskip=\s_spac_keep_unwanted_space\else
\hskip\s_spac_keep_unwanted_space\relax
\fi
\fi}
-\unexpanded\def\removeunwantedspaces
+\permanent\protected\def\removeunwantedspaces
{\ifhmode
\expandafter \spac_helpers_remove_unwantedspace
\fi}
@@ -578,7 +556,7 @@
\fi
\fi}
-\unexpanded\def\onlynonbreakablespace
+\permanent\protected\def\onlynonbreakablespace
{\ifdim\lastskip=\interwordspace
\unskip
\nonbreakablespace
@@ -609,34 +587,25 @@
%D A couple of plain macros:
-\ifdefined\thinspace \else
+\ifdefined\enspace \else \permanent\protected\def\enspace{\kern .5\emwidth} \fi
+\ifdefined\quad \else \permanent\protected\def\quad {\hskip \emwidth\relax} \fi
+\ifdefined\enskip \else \permanent\protected\def\enskip {\hskip.5\emwidth\relax} \fi
+\ifdefined\qquad \else \permanent\protected\def\qquad {\hskip 2\emwidth\relax} \fi
- \unexpanded\def\thinspace {\kern .16667\emwidth}
- \unexpanded\def\negthinspace{\kern-.16667\emwidth}
- \unexpanded\def\enspace {\kern .5\emwidth}
-
-\fi
-
-\ifdefined\quad \else
-
- \unexpanded\def\enskip{\hskip.5\emwidth\relax}
- \unexpanded\def\quad {\hskip \emwidth\relax}
- \unexpanded\def\qquad {\hskip 2\emwidth\relax}
-
-\fi
-
-\unexpanded\def\negenspace{\kern-.5\emwidth}
-\unexpanded\def\negemspace{\kern- \emwidth}
+\permanent\protected\def\negenspace{\kern-.5\emwidth}
+\permanent\protected\def\negemspace{\kern- \emwidth}
\let\emspace\quad
-\unexpanded\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers)
-
-\unexpanded\def\quads
- {\dosingleempty\spac_quads}
+\permanent\protected\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers)
-\def\spac_quads[#1]%
- {\zwj\dorecurse{\iffirstargument#1\else\plusthree\fi}{\hskip\emwidth\zwj}}
+\permanent\tolerant\protected\def\quads[#1]% we do robust checking
+ {\dontleavehmode
+ \begingroup
+ %\scratchcounter\ifparameter#1\or#1\else\plusthree\fi
+ \scratchcounter\ifchknum#1\or#1\else\plusthree\fi
+ \zwj\dorecurse\scratchcounter{\hskip\emwidth\zwj}%
+ \endgroup}
% Suggested by GB (not the name -):
@@ -652,16 +621,16 @@
\newskip\s_spac_neg_fill \s_spac_neg_fill = \zeropoint \s!plus-1\s!fill \relax
\newskip\s_spac_neg_filll \s_spac_neg_filll = \zeropoint \s!plus-1\s!filll\relax
-\unexpanded\def\hfilll {\hskip\s_spac_filll\relax}
-\unexpanded\def\vfilll {\vskip\s_spac_filll\relax}
+\permanent\protected\def\hfilll {\hskip\s_spac_filll\relax}
+\permanent\protected\def\vfilll {\vskip\s_spac_filll\relax}
-\unexpanded\def\hfillneg {\hskip\s_spac_neg_fill \relax}
-\unexpanded\def\hfilllneg{\hskip\s_spac_neg_filll\relax}
-\unexpanded\def\vfillneg {\vskip\s_spac_neg_fill \relax}
-\unexpanded\def\vfilllneg{\vskip\s_spac_neg_filll\relax}
+\permanent\protected\def\hfillneg {\hskip\s_spac_neg_fill \relax}
+\permanent\protected\def\hfilllneg{\hskip\s_spac_neg_filll\relax}
+\permanent\protected\def\vfillneg {\vskip\s_spac_neg_fill \relax}
+\permanent\protected\def\vfilllneg{\vskip\s_spac_neg_filll\relax}
-\unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup}
-\unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere
+\permanent\protected\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup}
+\permanent\protected\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere
% maybe we should hash the analysis
@@ -683,14 +652,14 @@
\c!default=\v!middle]
\appendtoks
- \setuevalue{\e!start\currentnarrower}{\spac_narrower_start{\currentnarrower}}%
+ \setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}%
\setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}%
\to \everydefinenarrower
-\unexpanded\def\installnarrowermethod#1#2%
+\permanent\protected\def\installnarrowermethod#1#2%
{\setvalue{\??narrowermethod#1}{#2}}
-\unexpanded\def\spac_narrower_method_analyze#1%
+\protected\def\spac_narrower_method_analyze#1%
{\ifcsname\??narrowermethod#1\endcsname
\lastnamedcs
\else
@@ -712,20 +681,17 @@
\installnarrowermethod \v!none {}
\installnarrowermethod \v!reverse {} % never seen
-\unexpanded\def\spac_narrower_start#1%
+\permanent\overloaded\tolerant\protected\def\spac_narrower_start[#1]#*[#2]%
{\begingroup
\edef\currentnarrower{#1}%
- \dosingleempty\spac_narrower_start_indeed}
-
-\unexpanded\def\spac_narrower_start_indeed[#1]%
- {\iffirstargument
- \spac_narrower_start_apply{#1}%
+ \ifparameter#2\or
+ \spac_narrower_start_apply{#2}%
\else
\spac_narrower_start_apply{\narrowerparameter\v!default}%
\fi}
-\newskip\s_spac_narrower_left_last
-\newskip\s_spac_narrower_right_last
+\newskip \s_spac_narrower_left_last
+\newskip \s_spac_narrower_right_last
\newconditional\s_spac_narrower_last_swap
\def\spac_narrower_start_apply#1%
@@ -736,22 +702,22 @@
\edef\askednarrower{#1}%
\ifx\askednarrower\v!reverse
\ifconditional\s_spac_narrower_last_swap
- \frozen\leftskip \s_spac_narrower_right_last
- \frozen\rightskip\s_spac_narrower_left_last
+ \permanent\leftskip \s_spac_narrower_right_last
+ \permanent\rightskip\s_spac_narrower_left_last
\setfalse\s_spac_narrower_last_swap
\else
- \frozen\leftskip \s_spac_narrower_left_last
- \frozen\rightskip\s_spac_narrower_right_last
+ \permanent\leftskip \s_spac_narrower_left_last
+ \permanent\rightskip\s_spac_narrower_right_last
\settrue\s_spac_narrower_last_swap
\fi
\else
\normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize
- \frozen\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
- \frozen\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
+ \permanent\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
+ \permanent\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
\fi
\seteffectivehsize}
-\unexpanded\def\spac_narrower_stop
+\permanent\protected\def\spac_narrower_stop
{\narrowerparameter\c!after
\normalexpanded{%
\endgroup
@@ -764,13 +730,15 @@
\fi
}}
-\unexpanded\def\startnarrower
- {\dosingleempty\spac_narrower_start_basic}
+%% \permanent\protected\def\startnarrower
+%% {\dosingleempty\spac_narrower_start_basic}
+%%
+%% \protected\def\spac_narrower_start_basic[#1]%
-\unexpanded\def\spac_narrower_start_basic[#1]%
+\permanent\tolerant\protected\def\startnarrower[#1]%
{\begingroup
\let\currentnarrower\empty
- \iffirstargument
+ \ifparameter#1\or
\spac_narrower_start_apply{#1}%
\else
\spac_narrower_start_apply{\narrowerparameter\v!default}%
@@ -778,24 +746,26 @@
\let\stopnarrower\spac_narrower_stop
-\unexpanded\def\startnarrow % current how
- {\begingroup
- \dodoubleempty\spac_narrower_start_named}
+%% \protected\def\startnarrow % current how
+%% {\begingroup
+%% \dodoubleempty\spac_narrower_start_named}
+%%
+%% \def\spac_narrower_start_named
+%% {\ifsecondargument
+%% \expandafter\spac_narrower_start_named_two
+%% \else
+%% \expandafter\spac_narrower_start_named_one
+%% \fi}
-% \def\spac_narrower_start_named[#1][#2]%
-% {\edef\currentnarrower{#1}%
-% \ifsecondargument
-% \spac_narrower_start_apply{#2}%
-% \else
-% \spac_narrower_start_apply{\narrowerparameter\v!default}%
-% \fi}
+% can be cleaned up more ... todo
-\def\spac_narrower_start_named
- {\ifsecondargument
+\permanent\tolerant\protected\def\startnarrow[#1]#*[#2]% current how
+ {\begingroup
+ \ifnum\lastarguments=\plustwo
\expandafter\spac_narrower_start_named_two
\else
\expandafter\spac_narrower_start_named_one
- \fi}
+ \fi[#1][#2]}
\def\spac_narrower_start_named_one[#1]%
{\doifelseassignment{#1}\spac_narrower_start_named_one_yes\spac_narrower_start_named_one_nop[#1]}
@@ -833,7 +803,7 @@
\newdimen\d_spac_effective_leftskip \def\effectiveleftskip {\dimexpr\leftskip \relax}
\newdimen\d_spac_effective_rightskip \def\effectiverightskip{\dimexpr\rightskip\relax}
-\unexpanded\def\seteffectivehsize
+\permanent\protected\def\seteffectivehsize
{\setlocalhsize
\d_spac_effective_hsize \localhsize
\d_spac_effective_leftskip 1\leftskip
@@ -861,16 +831,16 @@
\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname
\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname
-% \unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
-% \unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
+% \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}
-\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax}
-\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax}
+\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}
-\unexpanded\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\frozen\advance\leftskip \leftskipadaption }
-\unexpanded\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\frozen\advance\rightskip\rightskipadaption}
+\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\permanent\advance\leftskip \leftskipadaption }
+\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\permanent\advance\rightskip\rightskipadaption}
-\unexpanded\def\forgetbothskips
+\permanent\protected\def\forgetbothskips
{\leftskip\zeropoint
\rightskip\zeropoint
\relax}
@@ -881,7 +851,7 @@
% in spac-ver.mkiv
%
-% \unexpanded\def\forgetparskip
+% \protected\def\forgetparskip
% {\s_spac_whitespace_parskip\zeropoint
% \parskip\zeropoint
% \let\v_spac_whitespace_current\v!none}
@@ -894,7 +864,7 @@
\installcorenamespace{tolerancemethods}
-\unexpanded\def\installtolerancemethod#1#2#3%
+\permanent\protected\def\installtolerancemethod#1#2#3%
{\setvalue{\??tolerancemethods#1:#2}{#3}}
\installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty}
@@ -917,13 +887,20 @@
\def\spac_tolerances_step_vertical #1{\csname\??tolerancemethods\v!vertical :#1\endcsname}
\def\spac_tolerances_step_horizontal#1{\csname\??tolerancemethods\v!horizontal:#1\endcsname}
-\unexpanded\def\setuptolerance
- {\dosingleargument\spac_tolerances_setup}
-
-\def\spac_tolerances_setup[#1]%
- {\doifelseinset\v!vertical{#1}%
- {\processcommacommand[#1]\spac_tolerances_step_vertical }
- {\processcommacommand[#1]\spac_tolerances_step_horizontal}}
+%% \protected\def\setuptolerance
+%% {\dosingleargument\spac_tolerances_setup}
+%%
+%% \def\spac_tolerances_setup[#1]%
+%% {\doifelseinset\v!vertical{#1}%
+%% {\processcommacommand[#1]\spac_tolerances_step_vertical }
+%% {\processcommacommand[#1]\spac_tolerances_step_horizontal}}
+
+\permanent\tolerant\protected\def\setuptolerance[#1]%
+ {\ifarguments\or
+ \doifelseinset\v!vertical{#1}%
+ {\processcommacommand[#1]\spac_tolerances_step_vertical }
+ {\processcommacommand[#1]\spac_tolerances_step_horizontal}%
+ \fi}
%D \macros
%D {pushindentation,popindentation}
@@ -933,7 +910,7 @@
\newbox\b_spac_indentations_a
\newbox\b_spac_indentations_b
-\unexpanded\def\pushindentation
+\permanent\protected\def\pushindentation
{\begingroup
\ifhmode
\unskip
@@ -948,7 +925,7 @@
\setbox\b_spac_indentations_b\emptybox
\fi}
-\unexpanded\def\popindentation
+\permanent\protected\def\popindentation
{\box\b_spac_indentations_b
\box\b_spac_indentations_a
\endgroup}
@@ -1017,16 +994,16 @@
%D \ruledvtop{\typebuffer}}
%D \stoptyping
-\unexpanded\def\justonespace{\removeunwantedspaces\space}
-%unexpanded\def\justaperiod {\removeunwantedspaces.}
-%unexpanded\def\justacomma {\removeunwantedspaces,}
+\permanent\protected\def\justonespace{\removeunwantedspaces\space}
+%frozen\protected\def\justaperiod {\removeunwantedspaces.}
+%frozen\protected\def\justacomma {\removeunwantedspaces,}
\installcorenamespace{hspace}
-\unexpanded\def\ignorecrlf
+\permanent\protected\def\ignorecrlf
{\let\crlf\justonespace\let\\\crlf}
-\unexpanded\def\definehspace
+\permanent\protected\def\definehspace
{\dotripleempty\spac_hspaces_define}
\def\spac_hspaces_define[#1][#2][#3]% #1 = optional namespace
@@ -1036,28 +1013,23 @@
\setvalue{\??hspace:#1}{#2}%
\fi}
-\unexpanded\def\hspace
- {\dodoubleempty\spac_hspaces_insert}
-
-\def\spac_hspaces_insert[#1][#2]%
+\permanent\tolerant\protected\def\hspace[#1]#*[#2]%
{\ifhmode
\removeunwantedspaces
\hskip % always a skip even when 0pt
- \ifsecondargument
+ \ifparameter#2\or
\hspaceamount{#1}{#2}%
- \orelse\iffirstargument
+ \orelse\ifparameter#1\or
\hspaceamount\empty{#1}%
\else
\hspaceamount\empty\s!default
\fi
+ \relax
\expandafter\ignorespaces
\fi}
-\def\hspaceamount#1#2%
- {\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax}
-
-\def\directhspaceamount#1%
- {\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+\permanent\overloaded\def\hspaceamount #1#2{\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+\permanent\overloaded\def\directhspaceamount #1{\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
% no installhspace here (this is already an old command)
@@ -1071,56 +1043,55 @@
%D Taken from Taco's math module (cq. \AMS\ macros), but
%D adapted to \type {\hspace}:
-\unexpanded\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax}
-\unexpanded\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax}
-\unexpanded\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax}
+\permanent\protected\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax}
+\permanent\protected\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax}
+\permanent\protected\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax}
\newmuskip\hairmuskip \hairmuskip=.15mu
-\unexpanded\def\hairspace {\textormathspace+\hairmuskip{.5}}
-\unexpanded\def\thinspace {\textormathspace+\thinmuskip 1}
-%unexpanded\def\medspace {\textormathspace+\medmuskip 2} % 4/18 em
-\unexpanded\def\thickspace {\textormathspace+\thickmuskip3}
-\unexpanded\def\neghairspace {\textormathspace-\thinmuskip{.5}}
-\unexpanded\def\negthinspace {\textormathspace-\thinmuskip 1}
-\unexpanded\def\negmedspace {\textormathspace-\medmuskip 2}
-\unexpanded\def\negthickspace{\textormathspace-\thickmuskip3}
-
-\unexpanded\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}}
+\overloaded\permanent\protected \def\hairspace {\textormathspace+\hairmuskip{.5}}
+\overloaded\permanent\protected \def\thinspace {\textormathspace+\thinmuskip 1}
+%overloaded\permanent\protected \def\medspace {\textormathspace+\medmuskip 2} % 4/18 em
+\overloaded\permanent\protected \def\thickspace {\textormathspace+\thickmuskip3}
+\overloaded\permanent\protected \def\neghairspace {\textormathspace-\thinmuskip{.5}}
+\overloaded\permanent\protected \def\negthinspace {\textormathspace-\thinmuskip 1}
+\overloaded\permanent\protected \def\negmedspace {\textormathspace-\medmuskip 2}
+\overloaded\permanent\protected \def\negthickspace{\textormathspace-\thickmuskip3}
+\overloaded\permanent\protected\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}}
% needed for unicode:
-%unexpanded\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1}
-%unexpanded\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace
-%unexpanded\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax}
-%unexpanded\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax}
-%unexpanded\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie
-%unexpanded\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax}
-%unexpanded\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this
-%unexpanded\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup}
-%unexpanded\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax}
-%unexpanded\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax}
-%unexpanded\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace}
-%unexpanded\def\narrownobreakspace {\penalty\plustenthousand\thinspace}
-%unexpanded\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint}
-%unexpanded\def\zerowidthspace {\hskip\zeropoint}
+%protected\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1}
+%protected\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace
+%protected\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax}
+%protected\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax}
+%protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie
+%protected\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax}
+%protected\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this
+%protected\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup}
+%protected\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax}
+%protected\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax}
+%protected\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace}
+%protected\def\narrownobreakspace {\penalty\plustenthousand\thinspace}
+%protected\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint}
+%protected\def\zerowidthspace {\hskip\zeropoint}
\definehspace[.5][.1250\emwidth] % hair
\definehspace[1] [.1667\emwidth] % thin
\definehspace[2] [.2222\emwidth] % med
\definehspace[3] [.2777\emwidth] % thick
-\let \, \thinspace
-\let \: \medspace
-\let \; \thickspace
-\let \! \negthinspace
+\aliased\let \, \thinspace
+\aliased\let \: \medspace
+\aliased\let \; \thickspace
+\aliased\let \! \negthinspace
% plain ...
%
-% \ifdefined\> \else \unexpanded\def\>{\mskip \medmuskip } \fi
-% \ifdefined\* \else \unexpanded\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
+% \ifdefined\> \else \protected\def\>{\mskip \medmuskip } \fi
+% \ifdefined\* \else \protected\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
-\def\flexiblespaceamount#1#2#3%
+\permanent\def\flexiblespaceamount#1#2#3%
{#1\interwordspace
\s!plus#2\interwordstretch
\s!minus#3\interwordshrink}
@@ -1136,37 +1107,37 @@
\installcorenamespace{spacemethods}
-\unexpanded\def\installspacemethod#1#2% needs to set \obeyedspace
+\permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace
{\setvalue{\??spacemethods#1}{#2}}
-\def\activatespacehandler#1%
+\permanent\def\activatespacehandler#1%
{\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname}
-\unexpanded\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}%
-\unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}%
-\unexpanded\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}%
+\permanent\protected\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}%
+\permanent\protected\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}%
+\permanent\protected\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}%
% hm, order matters when we \let in \obeyspaces
\installspacemethod \v!on
{\obeyspaces
- \let\obeyedspace\spac_spaces_checked_control
- \let\ =\obeyedspace}
+ \enforced\let\obeyedspace\spac_spaces_checked_control
+ \enforced\let\ =\obeyedspace}
\installspacemethod \v!yes
{\obeyspaces
- \let\obeyedspace\spac_spaces_checked_normal
- \let\ =\obeyedspace}
+ \enforced\let\obeyedspace\spac_spaces_checked_normal
+ \enforced\let\ =\obeyedspace}
\installspacemethod \v!off % == default
{\normalspaces
- \let\obeyedspace\normalspace
- \let\ =\normalspaceprimitive} % was \normalspace
+ \enforced\let\obeyedspace\normalspace
+ \enforced\let\ =\normalspaceprimitive} % was \normalspace
\installspacemethod \v!fixed
{\obeyspaces
- \let\obeyedspace\spac_spaces_checked_fixed
- \let\ =\obeyedspace}
+ \enforced\let\obeyedspace\spac_spaces_checked_fixed
+ \enforced\let\ =\obeyedspace}
\appendtoks
\normalspaces % to be sure
@@ -1183,15 +1154,15 @@
%D
%D \typebuffer \getbuffer
-\unexpanded\def\autoinsertnextspace
+\permanent\protected\def\autoinsertnextspace
{\futurelet\nexttoken\spac_spaces_auto_insert_next}
-\def\spac_spaces_auto_insert_next
+\permanent\def\spac_spaces_auto_insert_next
{\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end
%D Moved from bib module:
-\unexpanded\def\outdented#1%
+\permanent\protected\def\outdented#1%
{\hskip-\hangindent#1\relax}
%D Beware: due to char-def this becomes an active character but that
@@ -1204,7 +1175,7 @@
% TODO (but used in languages):
-\unexpanded\def\spac_glues_text_or_math#1#2%
+\def\spac_glues_text_or_math#1#2%
{\begingroup
\ifmmode
\mskip#1%
@@ -1215,23 +1186,21 @@
\fi
\endgroup}
-\unexpanded\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small}
-\unexpanded\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium}
-\unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big}
+\permanent\protected\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small}
+\permanent\protected\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium}
+\permanent\protected\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big}
%D A rather unknown one:
-\unexpanded\def\widened % moved from cont-new
+\permanent\protected\def\widened % moved from cont-new
{\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop}
\def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}}
\def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}}
-\definecomplexorsimple\widened
-
%D For the moment here (used in page-txt):
-\unexpanded\def\ignoredlinebreak{\unskip\space\ignorespaces}
+\protected\def\ignoredlinebreak{\unskip\space\ignorespaces}
%D \macros
%D {startignorespaces}
@@ -1253,14 +1222,14 @@
\newsignal\s_spac_ignore_spaces
\newcount \c_spac_ignore_spaces
-\unexpanded\def\startignorespaces
+\protected\def\startignorespaces
{\advance\c_spac_ignore_spaces\plusone
\ifcase\c_spac_ignore_spaces\or \ifhmode
\hskip\s_spac_ignore_spaces
\fi \fi
\ignorespaces}
-\unexpanded\def\stopignorespaces
+\protected\def\stopignorespaces
{\ifcase\c_spac_ignore_spaces \or
\ifhmode
\doloop\spac_ignore_spaces_body
@@ -1285,11 +1254,11 @@
%D Something new:
-\unexpanded\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax}
-\unexpanded\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary}
+\protected\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax}
+\protected\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary}
-\unexpanded\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore}
-\unexpanded\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter}
-\unexpanded\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter}
+\protected\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore}
+\protected\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter}
+\protected\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter}
\protect \endinput
diff --git a/tex/context/base/mkiv/spac-lin.mkiv b/tex/context/base/mkiv/spac-lin.mkiv
index 640bcdaae..3d54b630a 100644
--- a/tex/context/base/mkiv/spac-lin.mkiv
+++ b/tex/context/base/mkiv/spac-lin.mkiv
@@ -171,7 +171,7 @@
\dostoptagged % can be a dummy one as we don't look ahead
\par
\dostarttagged\t!line\empty
- \futurelet\next\spac_lines_between}
+ \futurelet\nexttoken\spac_lines_between}
\unexpanded\def\spac_lines_stop
{\dostoptagged
@@ -182,10 +182,10 @@
\egroup}
\def\spac_lines_between
- {\ifx\next\spac_lines_stop
+ {\ifx\nexttoken\spac_lines_stop
\donefalse
\else
- \doifelsemeaning\next\obeyedline % brrr
+ \doifelsemeaning\nexttoken\obeyedline % brrr
{\donefalse\linesparameter\c!inbetween}
{\donetrue\spac_after_first_obeyed_line}%
\fi}
diff --git a/tex/context/base/mkiv/spac-par.mkiv b/tex/context/base/mkiv/spac-par.mkiv
index ee2d9c9cd..752d5c059 100644
--- a/tex/context/base/mkiv/spac-par.mkiv
+++ b/tex/context/base/mkiv/spac-par.mkiv
@@ -36,7 +36,8 @@
\hangafter \the\hangafter
\parskip \the\parskip
\leftskip \the\leftskip
- \rightskip \the\rightskip}}
+ \rightskip \the\rightskip
+ \relax}}
\unexpanded\def\pushparagraphproperties
{\edef\currentparagraphproperties{\carryoverpar\relax}%
diff --git a/tex/context/base/mkiv/spac-par.mkxl b/tex/context/base/mkiv/spac-par.mkxl
index e0eef0c67..524e31bc5 100644
--- a/tex/context/base/mkiv/spac-par.mkxl
+++ b/tex/context/base/mkiv/spac-par.mkxl
@@ -23,93 +23,75 @@
% this might move to syst-ini.mkxl
-\setnewconstant\frozenhsizecode "00000001
-\setnewconstant\frozenleftskipcode "00000002
-\setnewconstant\frozenrightskipcode "00000004
-\setnewconstant\frozenhangindentcode "00000008
-\setnewconstant\frozenhangaftercode "00000010
-\setnewconstant\frozenparindentcode "00000020
-\setnewconstant\frozenparfillskipcode "00000040
-\setnewconstant\frozenparfillleftskipcode "00000080
-\setnewconstant\frozenadjustspacingcode "00000100
-\setnewconstant\frozenprotrudecharscode "00000200
-\setnewconstant\frozenpretolerancecode "00000400
-\setnewconstant\frozentolerancecode "00000800
-\setnewconstant\frozenemergencystretchcode "00001000
-\setnewconstant\frozenloosenesscode "00002000
-\setnewconstant\frozenlastlinefitcode "00004000
-\setnewconstant\frozenlinepenaltycode "00008000
-\setnewconstant\frozeninterlinepenaltycode "00010000
-\setnewconstant\frozenclubpenaltycode "00020000
-\setnewconstant\frozenwidowpenaltycode "00040000
-\setnewconstant\frozendisplaywidowpenaltycode "00080000
-\setnewconstant\frozenbrokenpenaltycode "00100000
-\setnewconstant\frozenadjdemeritscode "00200000
-\setnewconstant\frozendoublehyphendemeritscode "00400000
-\setnewconstant\frozenfinalhyphendemeritscode "00800000
-\setnewconstant\frozenparshapecode "01000000
-\setnewconstant\frozeninterlinepenaltiescode "02000000
-\setnewconstant\frozenclubpenaltiescode "04000000
-\setnewconstant\frozenwidowpenaltiescode "08000000
-\setnewconstant\frozendisplaywidowpenaltiescode "10000000
-
\setnewconstant\paragraphupdatecodes\numexpr
\frozentolerancecode
+ \frozenloosenesscode
+ \frozenlinepenaltycode
- + \frozeninterlinepenaltycode
+ \frozenwidowpenaltycode
+ \frozenclubpenaltycode
+ \frozenbrokenpenaltycode
- + \frozenadjdemeritscode
- + \frozendoublehyphendemeritscode
- + \frozenfinalhyphendemeritscode
- + \frozeninterlinepenaltiescode
- + \frozenwidowpenaltiescode
- + \frozenclubpenaltiescode
+ + \frozendemeritscode
\relax
\setnewconstant\paragraphpenaltycodes\numexpr
- \frozeninterlinepenaltycode
+ \frozenlinepenaltycode
+ \frozenwidowpenaltycode
+ \frozenclubpenaltycode
+ \frozenbrokenpenaltycode
- + \frozeninterlinepenaltiescode
- + \frozenwidowpenaltiescode
- + \frozenclubpenaltiescode
\relax
\setnewconstant\paragraphdemeritcodes\numexpr
- \frozenadjdemeritscode
- + \frozendoublehyphendemeritscode
- + \frozenfinalhyphendemeritscode
+ \frozendemeritscode
\relax
-% + \frozenparskipcode
-
\setnewconstant\paragraphshapecodes\numexpr
- \frozenhangindentcode
- + \frozenhangaftercode
- + \frozenleftskipcode
- + \frozenrightskipcode
- + \frozenparfillskipcode
- + \frozenparshapecode
+ \frozenhangcode
+ + \frozenskipcode
+ + \frozenparfillcode
+ + \frozenshapecode
\relax
-\protected\def\freezeparagraphproperties {\snapshotpar\maxcount}
-\protected\def\defrostparagraphproperties{\snapshotpar\zerocount}
+\setnewconstant\frozenparagraphdefault\numexpr
+ \frozenhsizecode % \hsize
+ + \frozenskipcode % \leftskip \rightskip
+ + \frozenhangcode % \hangindent \hangafter
+ + \frozenindentcode % \parindent
+ + \frozenparfillcode % \parfillskip \parfillleftskip
+ + \frozenadjustcode % \adjustspacing
+ + \frozenprotrudecode % \protrudechars
+ + \frozentolerancecode % \tolerance \pretolerance
+ + \frozenstretchcode % \emergcystretch
+ + \frozenloosenesscode % \looseness
+ + \frozenlastlinecode % \lastlinefit
+ + \frozenlinepenaltycode % \linepenalty \interlinepenalty \interlinepenalties
+ + \frozenclubpenaltycode % \clubpenalty \clubpenalties
+ + \frozenwidowpenaltycode % \widowpenalty \widowpenalties
+ + \frozendisplaypenaltycode % \displaypenalty \displaypenalties
+ + \frozenbrokenpenaltycode % \brokenpenalty
+ + \frozendemeritscode % \doublehyphendemerits \finalhyphendemerits \adjdemerits
+ + \frozenshapecode % \parshape
+ % \frozenlinecode % \baselineskip \lineskip \lineskiplimit
+\relax
+
+\setnewconstant\paragraphlinecodes\numexpr
+ \frozenlinecode
+\relax
-\protected\def\updateparagraphproperties {\ifhmode\snapshotpar\paragraphupdatecodes \fi}
-\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi}
-\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi}
-\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi}
+\permanent\protected\def\freezeparagraphproperties {\snapshotpar\frozenparagraphdefault}
+\permanent\protected\def\defrostparagraphproperties{\snapshotpar\zerocount}
+
+\permanent\protected\def\updateparagraphproperties{\ifhmode\snapshotpar\paragraphupdatecodes \fi}
+\permanent\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi}
+\permanent\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi}
+\permanent\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi}
+\permanent\protected\def\updateparagraphlines {\ifhmode\snapshotpar\paragraphlinecodes \fi}
% so far
\let\spac_paragraph_freeze\relax
-\protected\def\setparagraphfreezing {\let\spac_paragraph_freeze\freezeparagraphproperties}
-\protected\def\forgetparagraphfreezing {\let\spac_paragraph_freeze\relax}
+\permanent\protected\def\setparagraphfreezing {\enforced\let\spac_paragraph_freeze\freezeparagraphproperties}
+\permanent\protected\def\forgetparagraphfreezing{\enforced\let\spac_paragraph_freeze\relax}
\installcorenamespace {bparwrap}
\installcorenamespace {eparwrap}
@@ -130,8 +112,8 @@
\wrapuppar{\the\csname\??eparwrap\the\c_spac_paragraph_group_level\endcsname\relax}%
\fi}
-\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre}
-\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp}
+\permanent\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre}
+\permanent\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp}
\protected\def\spac_paragraph_install
{\expandafter\newtoks\csname\??bparwrap\the\currentgrouplevel\endcsname
@@ -143,10 +125,8 @@
\def\spac_paragraph_install_pair#1#2#3%
{\expandafter\newtoks\csname\??parwrapbefore#3\endcsname
\expandafter\newtoks\csname\??parwrapafter #3\endcsname
- #1\csname\??bparwrap\the\currentgrouplevel\endcsname
- {\the\csname\??parwrapbefore#3\endcsname}%
- #2\csname\??eparwrap\the\currentgrouplevel\endcsname
- {\the\csname\??parwrapafter #3\endcsname}}
+ #1\csname\??bparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapbefore#3\endcsname}%
+ #2\csname\??eparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapafter #3\endcsname}}
\def\spac_register_par_wrapper_yes#1#2#3#4#5%
{\ifcsname\??bparwrap\the\currentgrouplevel\endcsname \else
@@ -162,7 +142,7 @@
\clf_setparwrapper{#3}#4}%
#2\csname\??parwrapafter #3\endcsname{#5}%
\clf_newparwrapper{#3}%
- \let\spac_paragraph_wrap\spac_paragraph_update}
+ \enforced\let\spac_paragraph_wrap\spac_paragraph_update}
\def\spac_register_par_wrapper_nop#1#2#3#4#5%
{\ifcsname\??parwrapcount#3\endcsname \else
@@ -178,34 +158,21 @@
\expandafter\spac_register_par_wrapper_yes
\fi}
-\protected\def\forgetparwrapper
+\permanent\protected\def\forgetparwrapper
{\csname\??bparwrap\the\currentgrouplevel\endcsname\emptytoks
\csname\??eparwrap\the\currentgrouplevel\endcsname\emptytoks}
-\protected\def\unregisterparwrapper#1%
+\permanent\protected\def\unregisterparwrapper#1%
{\csname\??parwrapcount#1\endcsname\zerocount
\ifcsname\??parwrapbefore#1\endcsname
\lastnamedcs\emptytoks
\csname\??parwrapafter#1\endcsname\emptytoks
\fi}
-\def\directparwrapper#1#2%
+\permanent\def\directparwrapper#1#2%
{#1\wrapuppar{#2}}
-% \protected\def\doifelseparwrapper#1%
-% {\ifcsname\??parwrapbefore#1\endcsname
-% \unless\iftok\lastnamedcs\emptytoks
-% \doubleexpandafter\firstoftwoarguments
-% \orelse\iftok\csname\??parwrapafter#1\endcsname\emptytoks
-% \doubleexpandafter\secondoftwoarguments
-% \else
-% \doubleexpandafter\firstoftwoarguments
-% \fi
-% \else
-% \expandafter\secondoftwoarguments
-% \fi}
-
-\protected\def\doifelseparwrapper#1%
+\permanent\protected\def\doifelseparwrapper#1%
{\unless\ifcsname\??parwrapcount#1\endcsname
\expandafter\secondoftwoarguments
\orelse\ifcase\lastnamedcs
@@ -217,7 +184,7 @@
% \getparwrapper % defined in lua
% \lastparwrapper % defined in lua
-\protected\def\showparwrapperstate#1%
+\permanent\protected\def\showparwrapperstate#1%
{\begingroup
\infofont ¶#1\hilo
{\smallinfofont\getparwrapper {#1}}%
@@ -230,7 +197,7 @@
\setparagraphfreezing
-\appendtoks\let\spac_paragraph_wrap\relax\to\everyforgetall
+\appendtoks\enforced\let\spac_paragraph_wrap\relax\to\everyforgetall
%D In due time, the code below will be upgraded using the above mechanisms.
@@ -240,24 +207,25 @@
%D indentation as set (by the output routine) inside the group are forgotten
%D afterwards. (I must not forget its existence).
-\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable !
+\permanent\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable !
{\normalexpanded
{\noexpand#1%
\hangindent\the\hangindent
\hangafter \the\hangafter
\parskip \the\parskip
\leftskip \the\leftskip
- \rightskip \the\rightskip}}
+ \rightskip \the\rightskip
+ \relax}}
-\unexpanded\def\pushparagraphproperties
+\permanent\protected\def\pushparagraphproperties
{\edef\currentparagraphproperties{\carryoverpar\relax}%
\pushmacro\currentparagraphproperties}
-\unexpanded\def\popparagraphproperties
+\permanent\protected\def\popparagraphproperties
{\popmacro\currentparagraphproperties
\currentparagraphproperties}
-\unexpanded\def\flushparagraphproperties
+\permanent\protected\def\flushparagraphproperties
{\popmacro\currentparagraphproperties}
%D Beware, changing this will break some code (like pos/backgrounds) but it has been
@@ -275,10 +243,7 @@
\newconditional\c_spac_paragraphs_intro_next
\newconditional\c_spac_paragraphs_intro_each
-\unexpanded\def\setupparagraphintro
- {\dodoubleempty\spac_paragraphs_intro}
-
-\unexpanded\def\spac_paragraphs_intro[#1][#2]%
+\permanent\protected\tolerant\def\setupparagraphintro[#1]#*[#2]%
{\def\spac_paragraphs_intro_step##1%
{\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}%
\processcommacommand[#1]\spac_paragraphs_intro_step}
@@ -345,7 +310,7 @@
%D some paragraph \par
%D \stoptyping
-\unexpanded\def\flushatparagraph#1%
+\permanent\protected\def\flushatparagraph#1%
{\global\c_spac_paragraphs_intro_first\plusone
\gtoksapp\t_spac_paragraphs_intro_first{#1}%
\glet\insertparagraphintro\spac_paragraphs_flush_intro}
@@ -353,7 +318,7 @@
%D Here comes the flusher (we misuse the one level expansion of token registers to
%D feed a nice stream into the paragraph.)
-\unexpanded\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly
+\protected\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly
{\normalexpanded{% % after another so the first code is there twice
\ifconditional\c_spac_paragraphs_intro_each
\ifconditional\c_spac_paragraphs_intro_next
@@ -378,7 +343,7 @@
\fi
\fi}}
-\unexpanded\def\spac_paragraphs_flush_intro_next
+\protected\def\spac_paragraphs_flush_intro_next
{\normalexpanded{%
\global\setfalse\c_spac_paragraphs_intro_next
\global\t_spac_paragraphs_intro_next\emptytoks
@@ -391,7 +356,7 @@
\the\t_spac_paragraphs_intro_next
\fi}}
-\unexpanded\def\spac_paragraphs_flush_intro_each
+\protected\def\spac_paragraphs_flush_intro_each
{\the\t_spac_paragraphs_intro_each}
%D \macros
@@ -409,11 +374,11 @@
%
% \initializeboxstack\??postponednodesstack
%
-% \unexpanded\def\pushpostponednodedata
+% \protected\def\pushpostponednodedata
% {\global\advance\c_spac_postponed_data\plusone
% \savebox\??postponednodesstack{\the\c_spac_postponed_data}{\box\b_spac_postponed_data}}
%
-% \unexpanded\def\poppostponednodedata
+% \protected\def\poppostponednodedata
% {\global\setbox\b_spac_postponed_data\hbox{\foundbox\??postponednodesstack{\the\c_spac_postponed_data}}%
% \global\advance\c_spac_postponed_data\minusone
% \ifvoid\b_spac_postponed_data\else
@@ -422,16 +387,16 @@
\newtoks\everyflushatnextpar
-\unexpanded\def\pushpostponednodedata
+\permanent\protected\def\pushpostponednodedata
{\globalpushbox\b_spac_postponed_data}
-\unexpanded\def\poppostponednodedata
+\permanent\protected\def\poppostponednodedata
{\globalpopbox\b_spac_postponed_data
\ifvoid\b_spac_postponed_data\else
\glet\flushpostponednodedata\spac_postponed_data_flush
\fi}
-\unexpanded\def\flushatnextpar
+\permanent\protected\def\flushatnextpar
{\begingroup
\the\everyflushatnextpar
\glet\flushpostponednodedata\spac_postponed_data_flush
@@ -471,7 +436,7 @@
\glet\flushpostponednodedata\relax
}%\fi}
-\unexpanded\def\doflushatpar % might be renamed
+\permanent\protected\def\doflushatpar % might be renamed
{\ifvmode
\expandafter\flushatnextpar
\else
diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua
index 7731b21f7..2223c7730 100644
--- a/tex/context/base/mkiv/spac-prf.lua
+++ b/tex/context/base/mkiv/spac-prf.lua
@@ -17,7 +17,6 @@ local formatters = string.formatters
local nodecodes = nodes.nodecodes
local gluecodes = nodes.gluecodes
local listcodes = nodes.listcodes
-local leadercodes = nodes.leadercodes
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
@@ -31,8 +30,7 @@ local math_code = nodecodes.math
local rule_code = nodecodes.rule
local marginkern_code = nodecodes.marginkern
-local leaders_code = leadercodes.leaders
-
+local leaders_code = gluecodes.leaders
local lineskip_code = gluecodes.lineskip
local baselineskip_code = gluecodes.baselineskip
diff --git a/tex/context/base/mkiv/spac-ver.lmt b/tex/context/base/mkiv/spac-ver.lmt
new file mode 100644
index 000000000..bfbcdf772
--- /dev/null
+++ b/tex/context/base/mkiv/spac-ver.lmt
@@ -0,0 +1,2623 @@
+if not modules then modules = { } end modules ['spac-ver'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to spac-ver.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we also need to call the spacer for inserts!
+
+-- somehow lists still don't always have proper prev nodes so i need to
+-- check all of the luatex code some day .. maybe i should replece the
+-- whole mvl handler by lua code .. why not
+
+-- todo: use lua nodes with lua data (>0.79)
+-- see ** can go when 0.79
+
+-- needs to be redone, too many calls and tests now ... still within some
+-- luatex limitations
+
+-- this code dates from the beginning and is kind of experimental; it
+-- will be optimized and improved soon .. it's way too complex now but
+-- dates from less possibilities
+--
+-- the collapser will be redone with user nodes; also, we might get make
+-- parskip into an attribute and appy it explicitly thereby getting rid
+-- of automated injections; eventually i want to get rid of the currently
+-- still needed tex -> lua -> tex > lua chain (needed because we can have
+-- expandable settings at the tex end
+
+-- todo: strip baselineskip around display math
+
+local next, type, tonumber = next, type, tonumber
+local gmatch, concat = string.gmatch, table.concat
+local ceil, floor = math.ceil, math.floor
+local lpegmatch = lpeg.match
+local unpack = unpack or table.unpack
+local allocate = utilities.storage.allocate
+local todimen = string.todimen
+local formatters = string.formatters
+local abs = math.abs
+
+local nodes = nodes
+local trackers = trackers
+local attributes = attributes
+local context = context
+local tex = tex
+
+local texlists = tex.lists
+local texget = tex.get
+local texgetcount = tex.getcount
+local texgetdimen = tex.getdimen
+local texset = tex.set
+local texsetdimen = tex.setdimen
+local texsetcount = tex.setcount
+local texnest = tex.nest
+local texgetbox = tex.getbox
+
+local buildpage = tex.triggerbuildpage
+
+local variables = interfaces.variables
+local implement = interfaces.implement
+
+local v_local = variables["local"]
+local v_global = variables["global"]
+local v_box = variables.box
+----- v_page = variables.page -- reserved for future use
+local v_split = variables.split
+local v_min = variables.min
+local v_max = variables.max
+local v_none = variables.none
+local v_line = variables.line
+local v_noheight = variables.noheight
+local v_nodepth = variables.nodepth
+local v_line = variables.line
+local v_halfline = variables.halfline
+local v_line_m = "-" .. v_line
+local v_halfline_m = "-" .. v_halfline
+local v_first = variables.first
+local v_last = variables.last
+local v_top = variables.top
+local v_bottom = variables.bottom
+local v_minheight = variables.minheight
+local v_maxheight = variables.maxheight
+local v_mindepth = variables.mindepth
+local v_maxdepth = variables.maxdepth
+local v_offset = variables.offset
+local v_strut = variables.strut
+
+local v_hfraction = variables.hfraction
+local v_dfraction = variables.dfraction
+local v_bfraction = variables.bfraction
+local v_tlines = variables.tlines
+local v_blines = variables.blines
+
+-- vertical space handler
+
+local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end)
+local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end)
+local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end)
+local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end)
+local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end)
+local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end)
+local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end)
+
+local remove_math_skips = true directives.register("vspacing.removemathskips", function(v) remnove_math_skips = v end)
+
+local report_vspacing = logs.reporter("vspacing","spacing")
+local report_collapser = logs.reporter("vspacing","collapsing")
+local report_snapper = logs.reporter("vspacing","snapping")
+local report_specials = logs.reporter("vspacing","specials")
+
+local a_skipcategory = attributes.private('skipcategory')
+local a_skippenalty = attributes.private('skippenalty')
+local a_skiporder = attributes.private('skiporder')
+local a_snapmethod = attributes.private('snapmethod')
+local a_snapvbox = attributes.private('snapvbox')
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local setlink = nuts.setlink
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getattr = nuts.getattr
+local getattrs = nuts.getattrs
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local getwhd = nuts.getwhd
+local setwhd = nuts.setwhd
+local getprop = nuts.getprop
+local setprop = nuts.setprop
+local getglue = nuts.getglue
+local setglue = nuts.setglue
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local getwidth = nuts.getwidth
+local setheight = nuts.setheight
+local getheight = nuts.getheight
+local setdepth = nuts.setdepth
+local getdepth = nuts.getdepth
+local setnext = nuts.setnext
+
+local find_node_tail = nuts.tail
+local flush_node = nuts.flush_node
+local remove_node = nuts.remove
+local count_nodes = nuts.countall
+local hpack_node = nuts.hpack
+local vpack_node = nuts.vpack
+local start_of_par = nuts.start_of_par
+
+local write_node = nuts.write
+
+local nextnode = nuts.traversers.node
+local nexthlist = nuts.traversers.hlist
+
+local nodereference = nuts.reference
+
+local theprop = nuts.theprop
+
+local listtoutf = nodes.listtoutf
+local nodeidstostring = nodes.idstostring
+
+local nodepool = nuts.pool
+
+local new_penalty = nodepool.penalty
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+local new_rule = nodepool.rule
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+----- penaltycodes = nodes.penaltycodes
+----- listcodes = nodes.listcodes
+
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local rule_code = nodecodes.rule
+local par_code = nodecodes.par
+
+local userskip_code = gluecodes.userskip
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local parskip_code = gluecodes.parskip
+local topskip_code = gluecodes.topskip
+local splittopskip_code = gluecodes.splittopskip
+
+local linelist_code = nodes.listcodes.line
+
+local properties = nodes.properties.data
+
+local vspacing = builders.vspacing or { }
+builders.vspacing = vspacing
+
+local vspacingdata = vspacing.data or { }
+vspacing.data = vspacingdata
+
+local snapmethods = vspacingdata.snapmethods or { }
+vspacingdata.snapmethods = snapmethods
+
+storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods")
+
+do
+
+ local default = {
+ [v_maxheight] = true,
+ [v_maxdepth] = true,
+ [v_strut] = true,
+ [v_hfraction] = 1,
+ [v_dfraction] = 1,
+ [v_bfraction] = 0.25,
+ }
+
+ local fractions = {
+ [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction,
+ [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction,
+ [v_box] = v_bfraction,
+ [v_top] = v_tlines, [v_bottom] = v_blines,
+ }
+
+ local values = {
+ offset = "offset"
+ }
+
+ local colonsplitter = lpeg.splitat(":")
+
+ local function listtohash(str)
+ local t = { }
+ for s in gmatch(str,"[^, ]+") do
+ local key, detail = lpegmatch(colonsplitter,s)
+ local v = variables[key]
+ if v then
+ t[v] = true
+ if detail then
+ local k = fractions[key]
+ if k then
+ detail = tonumber("0" .. detail)
+ if detail then
+ t[k] = detail
+ end
+ else
+ k = values[key]
+ if k then
+ detail = todimen(detail)
+ if detail then
+ t[k] = detail
+ end
+ end
+ end
+ end
+ else
+ detail = tonumber("0" .. key)
+ if detail then
+ t[v_hfraction] = detail
+ t[v_dfraction] = detail
+ end
+ end
+ end
+ if next(t) then
+ t[v_hfraction] = t[v_hfraction] or 1
+ t[v_dfraction] = t[v_dfraction] or 1
+ return t
+ else
+ return default
+ end
+ end
+
+ function vspacing.definesnapmethod(name,method)
+ local n = #snapmethods + 1
+ local t = listtohash(method)
+ snapmethods[n] = t
+ t.name = name -- not interfaced
+ t.specification = method -- not interfaced
+ context(n)
+ end
+
+end
+
+local function validvbox(parentid,list)
+ if parentid == hlist_code then
+ local id = getid(list)
+ if id == par_code and start_of_par(list) then
+ list = getnext(list)
+ if not next then
+ return nil
+ end
+ end
+ local done = nil
+ for n, id in nextnode, list do
+ if id == vlist_code or id == hlist_code then
+ if done then
+ return nil
+ else
+ done = n
+ end
+ elseif id == glue_code or id == penalty_code then
+ -- go on
+ else
+ return nil -- whatever
+ end
+ end
+ if done then
+ local id = getid(done)
+ if id == hlist_code then
+ return validvbox(id,getlist(done))
+ end
+ end
+ return done -- only one vbox
+ end
+end
+
+local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped
+ -- problem: any snapped vbox ends up in a line
+ if list and parentid == hlist_code then
+ local id = getid(list)
+ if id == par_code and start_of_par(list) then
+ list = getnext(list)
+ if not list then
+ return false
+ end
+ end
+ for n, id in nextnode, list do
+ if id == hlist_code or id == vlist_code then
+ -- local a = getattr(n,a_snapmethod)
+ -- if not a then
+ -- -- return true -- not snapped at all
+ -- elseif a == 0 then
+ -- return true -- already snapped
+ -- end
+ local p = getprop(n,"snapper")
+ if p then
+ return p
+ end
+ elseif id == glue_code or id == penalty_code then -- or id == kern_code then
+ -- go on
+ else
+ return false -- whatever
+ end
+ end
+ end
+ return false
+end
+
+-- quite tricky: ceil(-something) => -0
+
+local function ceiled(n)
+ if n < 0 or n < 0.01 then
+ return 0
+ else
+ return ceil(n)
+ end
+end
+
+local function floored(n)
+ if n < 0 or n < 0.01 then
+ return 0
+ else
+ return floor(n)
+ end
+end
+
+-- check variables.none etc
+
+local function fixedprofile(current)
+ local profiling = builders.profiling
+ return profiling and profiling.fixedprofile(current)
+end
+
+local function snap_hlist(where,current,method,height,depth) -- method[v_strut] is default
+ if fixedprofile(current) then
+ return
+ end
+ local list = getlist(current)
+ local t = trace_vsnapping and { }
+ if t then
+ t[#t+1] = formatters["list content: %s"](listtoutf(list))
+ t[#t+1] = formatters["snap method: %s"](method.name) -- not interfaced
+ t[#t+1] = formatters["specification: %s"](method.specification) -- not interfaced
+ end
+ local snapht, snapdp
+ if method[v_local] then
+ -- snapping is done immediately here
+ snapht = texgetdimen("bodyfontstrutheight")
+ snapdp = texgetdimen("bodyfontstrutdepth")
+ if t then
+ t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ elseif method[v_global] then
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
+ if t then
+ t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ else
+ -- maybe autolocal
+ -- snapping might happen later in the otr
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
+ local lsnapht = texgetdimen("bodyfontstrutheight")
+ local lsnapdp = texgetdimen("bodyfontstrutdepth")
+ if snapht ~= lsnapht and snapdp ~= lsnapdp then
+ snapht, snapdp = lsnapht, lsnapdp
+ end
+ if t then
+ t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp)
+ end
+ end
+
+ local wd, ht, dp = getwhd(current)
+
+ local h = (method[v_noheight] and 0) or height or ht
+ local d = (method[v_nodepth] and 0) or depth or dp
+ local hr = method[v_hfraction] or 1
+ local dr = method[v_dfraction] or 1
+ local br = method[v_bfraction] or 0
+ local ch = h
+ local cd = d
+ local tlines = method[v_tlines] or 1
+ local blines = method[v_blines] or 1
+ local done = false
+ local plusht = snapht
+ local plusdp = snapdp
+ local snaphtdp = snapht + snapdp
+ local extra = 0
+
+ if t then
+ t[#t+1] = formatters["hlist: wd %p ht %p (used %p) dp %p (used %p)"](wd,ht,h,dp,d)
+ t[#t+1] = formatters["fractions: hfraction %s dfraction %s bfraction %s tlines %s blines %s"](hr,dr,br,tlines,blines)
+ end
+
+ if method[v_box] then
+ local br = 1 - br
+ if br < 0 then
+ br = 0
+ elseif br > 1 then
+ br = 1
+ end
+ local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_box,plusht,plusdp)
+ end
+ elseif method[v_max] then
+ local n = ceiled((h+d)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_max,plusht,plusdp)
+ end
+ elseif method[v_min] then
+ -- we catch a lone min
+ if method.specification ~= v_min then
+ local n = floored((h+d)/snaphtdp)
+ local x = n * snaphtdp - h - d
+ plusht = h + x / 2
+ plusdp = d + x / 2
+ if plusht < 0 then
+ plusht = 0
+ end
+ if plusdp < 0 then
+ plusdp = 0
+ end
+ end
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_min,plusht,plusdp)
+ end
+ elseif method[v_none] then
+ plusht, plusdp = 0, 0
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_none,0,0)
+ end
+ end
+ -- for now, we actually need to tag a box and then check at several points if something ended up
+ -- at the top of a page
+ if method[v_halfline] then -- extra halfline
+ extra = snaphtdp/2
+ plusht = plusht + extra
+ plusdp = plusdp + extra
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline,plusht,plusdp)
+ end
+ end
+ if method[v_line] then -- extra line
+ extra = snaphtdp
+ plusht = plusht + extra
+ plusdp = plusdp + extra
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line,plusht,plusdp)
+ end
+ end
+ if method[v_halfline_m] then -- extra halfline
+ extra = - snaphtdp/2
+ plusht = plusht + extra
+ plusdp = plusdp + extra
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline_m,plusht,plusdp)
+ end
+ end
+ if method[v_line_m] then -- extra line
+ extra = - snaphtdp
+ plusht = plusht + extra
+ plusdp = plusdp + extra
+ if t then
+ t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line_m,plusht,plusdp)
+ end
+ end
+ if method[v_first] then
+ local thebox = current
+ local id = getid(thebox)
+ if id == hlist_code then
+ thebox = validvbox(id,getlist(thebox))
+ id = thebox and getid(thebox)
+ end
+ if thebox and id == vlist_code then
+ local list = getlist(thebox)
+ local lw, lh, ld
+ for n in nexthlist, list do
+ lw, lh, ld = getwhd(n)
+ break
+ end
+ if lh then
+ local wd, ht, dp = getwhd(thebox)
+ if t then
+ t[#t+1] = formatters["first line: height %p depth %p"](lh,ld)
+ t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
+ end
+ local delta = h - lh
+ ch, cd = lh, delta + d
+ h, d = ch, cd
+ local shifted = hpack_node(getlist(current))
+ setshift(shifted,delta)
+ setlist(current,shifted)
+ done = true
+ if t then
+ t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta)
+ end
+ elseif t then
+ t[#t+1] = "first: not done, no content"
+ end
+ elseif t then
+ t[#t+1] = "first: not done, no vbox"
+ end
+ elseif method[v_last] then
+ local thebox = current
+ local id = getid(thebox)
+ if id == hlist_code then
+ thebox = validvbox(id,getlist(thebox))
+ id = thebox and getid(thebox)
+ end
+ if thebox and id == vlist_code then
+ local list = getlist(thebox)
+ local lw, lh, ld
+ for n in nexthlist, list do
+ lw, lh, ld = getwhd(n)
+ end
+ if lh then
+ local wd, ht, dp = getwhd(thebox)
+ if t then
+ t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld)
+ t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
+ end
+ local delta = d - ld
+ cd, ch = ld, delta + h
+ h, d = ch, cd
+ local shifted = hpack_node(getlist(current))
+ setshift(shifted,delta)
+ setlist(current,shifted)
+ done = true
+ if t then
+ t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta)
+ end
+ elseif t then
+ t[#t+1] = "last: not done, no content"
+ end
+ elseif t then
+ t[#t+1] = "last: not done, no vbox"
+ end
+ end
+ if method[v_minheight] then
+ ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht
+ if t then
+ t[#t+1] = formatters["minheight: %p"](ch)
+ end
+ elseif method[v_maxheight] then
+ ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht
+ if t then
+ t[#t+1] = formatters["maxheight: %p"](ch)
+ end
+ else
+ ch = plusht
+ if t then
+ t[#t+1] = formatters["set height: %p"](ch)
+ end
+ end
+ if method[v_mindepth] then
+ cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp
+ if t then
+ t[#t+1] = formatters["mindepth: %p"](cd)
+ end
+ elseif method[v_maxdepth] then
+ cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp
+ if t then
+ t[#t+1] = formatters["maxdepth: %p"](cd)
+ end
+ else
+ cd = plusdp
+ if t then
+ t[#t+1] = formatters["set depth: %p"](cd)
+ end
+ end
+ if method[v_top] then
+ ch = ch + tlines * snaphtdp
+ if t then
+ t[#t+1] = formatters["top height: %p"](ch)
+ end
+ end
+ if method[v_bottom] then
+ cd = cd + blines * snaphtdp
+ if t then
+ t[#t+1] = formatters["bottom depth: %p"](cd)
+ end
+ end
+ local offset = method[v_offset]
+ if offset then
+ -- we need to set the attr
+ if t then
+ local wd, ht, dp = getwhd(current)
+ t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp)
+ end
+ local shifted = hpack_node(getlist(current))
+ setshift(shifted,offset)
+ setlist(current,shifted)
+ if t then
+ local wd, ht, dp = getwhd(current)
+ t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp)
+ end
+ setattr(shifted,a_snapmethod,0)
+ setattr(current,a_snapmethod,0)
+ end
+ if not height then
+ setheight(current,ch)
+ if t then
+ t[#t+1] = formatters["forced height: %p"](ch)
+ end
+ end
+ if not depth then
+ setdepth(current,cd)
+ if t then
+ t[#t+1] = formatters["forced depth: %p"](cd)
+ end
+ end
+ local lines = (ch+cd)/snaphtdp
+ if t then
+ local original = (h+d)/snaphtdp
+ local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth"))
+ t[#t+1] = formatters["final lines : %p -> %p (%p)"](original,lines,whatever)
+ t[#t+1] = formatters["final height: %p -> %p"](h,ch)
+ t[#t+1] = formatters["final depth : %p -> %p"](d,cd)
+ end
+-- todo:
+--
+-- if h < 0 or d < 0 then
+-- h = 0
+-- d = 0
+-- end
+ if t then
+ report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t)
+ end
+ if not method[v_split] then
+ -- so extra will not be compensated at the top of a page
+ extra = 0
+ end
+ return h, d, ch, cd, lines, extra
+end
+
+local categories = {
+ [0] = "discard",
+ [1] = "largest",
+ [2] = "force",
+ [3] = "penalty",
+ [4] = "add",
+ [5] = "disable",
+ [6] = "nowhite",
+ [7] = "goback",
+ [8] = "packed",
+ [9] = "overlay",
+ [10] = "enable",
+ [11] = "notopskip",
+}
+
+categories = allocate(table.swapped(categories,categories))
+vspacing.categories = categories
+
+function vspacing.tocategories(str)
+ local t = { }
+ for s in gmatch(str,"[^, ]") do -- use lpeg instead
+ local n = tonumber(s)
+ if n then
+ t[categories[n]] = true
+ else
+ t[b] = true
+ end
+ end
+ return t
+end
+
+function vspacing.tocategory(str) -- can be optimized
+ if type(str) == "string" then
+ return set.tonumber(vspacing.tocategories(str))
+ else
+ return set.tonumber({ [categories[str]] = true })
+ end
+end
+
+vspacingdata.map = vspacingdata.map or { } -- allocate ?
+vspacingdata.skip = vspacingdata.skip or { } -- allocate ?
+
+storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map")
+storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip")
+
+do
+
+ local P, C, R, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs
+
+ vspacing.fixed = false
+
+ local map = vspacingdata.map
+ local skip = vspacingdata.skip
+
+ local sign = S("+-")^0
+ local multiplier = C(sign * R("09")^1) * P("*")
+ local singlefier = Cs(sign * Cc(1))
+ local separator = S(", ")
+ local category = P(":") * C((1-separator)^1)
+ local keyword = C((1-category-separator)^1)
+ local splitter = (multiplier + Cc(1)) * keyword * (category + Cc(false))
+
+ local k_fixed = variables.fixed
+ local k_flexible = variables.flexible
+ local k_category = "category"
+ local k_penalty = "penalty"
+ local k_order = "order"
+
+ function vspacing.setmap(from,to)
+ map[from] = to
+ end
+
+ function vspacing.setskip(key,value,grid)
+ if value ~= "" then
+ if grid == "" then grid = value end
+ skip[key] = { value, grid }
+ end
+ end
+
+ do -- old variant
+
+ local ctx_fixedblankskip = context.fixedblankskip
+ local ctx_flexibleblankskip = context.flexibleblankskip
+ local ctx_setblankcategory = context.setblankcategory
+ local ctx_setblankorder = context.setblankorder
+ local ctx_setblankpenalty = context.setblankpenalty
+ ----- ctx_setblankhandling = context.setblankhandling
+ local ctx_flushblankhandling = context.flushblankhandling
+ local ctx_addpredefinedblankskip = context.addpredefinedblankskip
+ local ctx_addaskedblankskip = context.addaskedblankskip
+ local ctx_setblankpacked = context.setblankpacked
+
+ local ctx_pushlogger = context.pushlogger
+ local ctx_startblankhandling = context.startblankhandling
+ local ctx_stopblankhandling = context.stopblankhandling
+ local ctx_poplogger = context.poplogger
+
+ local pattern = nil
+
+ local packed = categories.packed
+
+ local function handler(amount, keyword, detail)
+ if not keyword then
+ report_vspacing("unknown directive %a",s)
+ else
+ local mk = map[keyword]
+ if mk then
+ lpegmatch(pattern,mk)
+ elseif keyword == k_fixed then
+ ctx_fixedblankskip()
+ elseif keyword == k_flexible then
+ ctx_flexibleblankskip()
+ elseif keyword == k_category then
+ local category = tonumber(detail)
+ if category == packed then
+ ctx_setblankpacked()
+ elseif category then
+ ctx_setblankcategory(category)
+ ctx_flushblankhandling()
+ end
+ elseif keyword == k_order and detail then
+ local order = tonumber(detail)
+ if order then
+ ctx_setblankorder(order)
+ end
+ elseif keyword == k_penalty and detail then
+ local penalty = tonumber(detail)
+ if penalty then
+ ctx_setblankpenalty(penalty)
+ end
+ else
+ amount = tonumber(amount) or 1
+ local sk = skip[keyword]
+ if sk then
+ ctx_addpredefinedblankskip(amount,keyword)
+ else -- no check
+ ctx_addaskedblankskip(amount,keyword)
+ end
+ end
+ end
+ end
+
+ local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler
+ pattern = (splitter + separator^1)^0
+
+ function vspacing.analyze(str)
+ if trace_vspacing then
+ ctx_pushlogger(report_vspacing)
+ ctx_startblankhandling()
+ lpegmatch(pattern,str)
+ ctx_stopblankhandling()
+ ctx_poplogger()
+ else
+ ctx_startblankhandling()
+ lpegmatch(pattern,str)
+ ctx_stopblankhandling()
+ end
+ end
+
+ end
+
+ do -- new variant
+
+ local expandmacro = token.expand_macro
+ -- local runlocal = tex.runlocal
+ -- local setmacro = tokens.setters.macro
+ -- local settoks = tex.settoks
+ local toscaled = tex.toscaled
+
+ local setattrs = nuts.setattrs
+
+ local b_done = false
+ local b_packed = false
+
+ local b_amount = 0
+ local b_stretch = 0
+ local b_shrink = 0
+ local b_category = false
+ local b_penalty = false
+ local b_order = false
+ local b_fixed = false
+ local b_grid = false
+
+ local pattern = nil
+
+ local packed = categories.packed
+
+ local gluefactor = .25
+
+ local ctx_ignoreparskip = context.core.ignoreparskip
+
+ -- local ctx_vspacingfromtempstring = context.core.vspacingfromtempstring
+ -- local ctx_vspacingfromscratchtoks = context.core.vspacingfromscratchtoks
+
+ -- local ctx_vspacingpredefinedvalue = context.core.vspacingpredefinedvalue
+ --
+ -- local cache = table.setmetatableindex(function(t,k)
+ -- local v = function() ctx_vspacingpredefinedvalue(k) end
+ -- t[k] = v
+ -- return v
+ -- end)
+
+ local function before()
+ b_amount = 0
+ b_stretch = 0
+ b_shrink = 0
+ b_category = 1
+ b_penalty = false
+ b_order = false
+ b_fixed = b_grid
+ end
+
+ local function after()
+ if fixed then
+ b_stretch = 0
+ b_shrink = 0
+ else
+ b_stretch = gluefactor * b_amount
+ b_shrink = gluefactor * b_amount
+ end
+ end
+
+ -- use a cache for predefined ones
+
+ -- local function inject()
+ -- local n = new_glue(b_amount,b_stretch,b_shrink)
+ -- if b_category then
+ -- setattr(n,a_skipcategory,b_category)
+ -- end
+ -- if b_penalty then
+ -- setattr(n,a_skippenalty,b_penalty)
+ -- end
+ -- if b_order then
+ -- setattr(n,a_skiporder,b_order or 1)
+ -- end
+ -- write_node(n)
+ -- end
+
+ local function inject()
+ local n = new_glue(b_amount,b_stretch,b_shrink)
+ setattrs(n,false,a_skipcategory,b_category,a_skippenalty,b_penalty,a_skiporder,b_order or 1)
+ write_node(n)
+ end
+
+ local function flush()
+ after()
+ if b_done then
+ inject()
+ b_done = false
+ end
+ before()
+ end
+
+ -- local cmd = token.create("vspacingfromtempstring")
+ local cmd = token.create("vspacingpredefinedvalue")
+
+ local function handler(amount, keyword, detail)
+ if not keyword then
+ report_vspacing("unknown directive %a",s)
+ else
+ local mk = map[keyword]
+ if mk then
+ lpegmatch(pattern,mk)
+ elseif keyword == k_fixed then
+ b_fixed = true
+ elseif keyword == k_flexible then
+ b_flexible = false
+ elseif keyword == k_category then
+ local category = tonumber(detail)
+ if category == packed then
+ b_packed = true
+ elseif category then
+ b_category = category
+ b_done = true
+ flush()
+ end
+ elseif keyword == k_order and detail then
+ local order = tonumber(detail)
+ if order then
+ b_order = order
+ end
+ elseif keyword == k_penalty and detail then
+ local penalty = tonumber(detail)
+ if penalty then
+ flush()
+ b_done = true
+ b_category = 3
+ b_penalty = penalty
+ flush()
+ end
+ else
+ amount = tonumber(amount) or 1
+ local sk = skip[keyword]
+ if sk then
+ -- amount, keyword
+ b_done = true
+ -- best, for now, todo: runlocal with arguments
+ -- expandmacro("vspacingpredefinedvalue",true,keyword)
+ expandmacro(cmd,true,keyword)
+ -- setmacro("tempstring",keyword)
+ -- runlocal(cmd)
+ -- nicest
+ -- runlocal(cache[keyword])
+ -- fast
+ -- settoks("scratchtoks",keyword)
+ -- runlocal("vspacingfromscratchtoks")
+ -- middleground
+ -- setmacro("tempstring",keyword)
+ -- runlocal(ctx_vspacingfromtempstring)
+ --
+ b_amount = b_amount + amount * texgetdimen("scratchdimen")
+ else -- no check
+ b_done = true
+ b_amount = b_amount + amount * toscaled(keyword)
+ end
+ end
+ end
+ end
+
+ -- alternatively we can make a table and have a keyword -> split cache but this is probably
+ -- not really a bottleneck
+
+ local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler
+ pattern = (splitter + separator^1)^0
+
+ function vspacing.inject(grid,str)
+ if trace_vspacing then
+ -- ctx_pushlogger(report_vspacing)
+ end
+ b_done = false
+ b_packed = false
+ b_grid = gridsnapping
+ before()
+ lpegmatch(pattern,str)
+ after()
+ if b_done then
+ inject()
+ end
+ if b_packed then
+ ctx_ignoreparskip()
+ end
+ if trace_vspacing then
+ -- ctx_poplogger()
+ end
+ end
+
+ function vspacing.injectpenalty(penalty)
+ local n = new_glue()
+ setattrs(n,false,a_skipcategory,categories.penalty,a_skippenalty,penalty,a_skiporder,1)
+ write_node(n)
+ end
+
+ function vspacing.injectskip(amount)
+ local n = new_glue(amount)
+ setattrs(n,false,a_skipcategory,categories.largest,a_skippenalty,false,a_skiporder,1)
+ write_node(n)
+ end
+
+ function vspacing.injectdisable(amount)
+ local n = new_glue()
+ setattrs(n,false,a_skipcategory,categories.disable,a_skippenalty,false,a_skiporder,1)
+ write_node(n)
+ end
+
+ end
+
+end
+
+-- implementation
+
+-- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display
+
+function vspacing.snapbox(n,how)
+ local sv = snapmethods[how]
+ if sv then
+ local box = getbox(n)
+ local list = getlist(box)
+ if list then
+ local s = getattr(list,a_snapmethod)
+ if s == 0 then
+ if trace_vsnapping then
+ -- report_snapper("box list not snapped, already done")
+ end
+ else
+ local wd, ht, dp = getwhd(box)
+ if false then -- todo: already_done
+ -- assume that the box is already snapped
+ if trace_vsnapping then
+ report_snapper("box list already snapped at (%p,%p): %s",
+ ht,dp,listtoutf(list))
+ end
+ else
+ local h, d, ch, cd, lines, extra = snap_hlist("box",box,sv,ht,dp)
+ setprop(box,"snapper",{
+ ht = h,
+ dp = d,
+ ch = ch,
+ cd = cd,
+ extra = extra,
+ current = current,
+ })
+ setwhd(box,wd,ch,cd)
+ if trace_vsnapping then
+ report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
+ h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list))
+ end
+ setattr(box,a_snapmethod,0) --
+ setattr(list,a_snapmethod,0) -- yes or no
+ end
+ end
+ end
+ end
+end
+
+-- I need to figure out how to deal with the prevdepth that crosses pages. In fact,
+-- prevdepth is often quite interfering (even over a next paragraph) so I need to
+-- figure out a trick. Maybe use something other than a rule. If we visualize we'll
+-- see the baselineskip in action:
+--
+-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
+-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
+-- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page
+
+-- We can register and copy the rule instead.
+
+do
+
+ local insert_node_after = nuts.insert_after
+ local insert_node_before = nuts.insert_before
+
+ local abovedisplayskip_code = gluecodes.abovedisplayskip
+ local belowdisplayskip_code = gluecodes.belowdisplayskip
+ local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip
+ local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip
+
+ local w, h, d = 0, 0, 0
+ ----- w, h, d = 100*65536, 65536, 65536
+
+ local trace_list = { }
+ local tracing_info = { }
+ local before = ""
+ local after = ""
+
+ local function nodes_to_string(head)
+ local current = head
+ local t = { }
+ while current do
+ local id = getid(current)
+ local ty = nodecodes[id]
+ if id == penalty_code then
+ t[#t+1] = formatters["%s:%s"](ty,getpenalty(current))
+ elseif id == glue_code then
+ t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current))
+ elseif id == kern_code then
+ t[#t+1] = formatters["%s:%p"](ty,getkern(current))
+ else
+ t[#t+1] = ty
+ end
+ current = getnext(current)
+ end
+ return concat(t," + ")
+ end
+
+ local function reset_tracing(head)
+ trace_list, tracing_info, before, after = { }, false, nodes_to_string(head), ""
+ end
+
+ local function trace_skip(str,sc,so,sp,data)
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getwidth(data), sc or "-", so or "-", sp or "-") }
+ tracing_info = true
+ end
+
+ local function trace_natural(str,data)
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getwidth(data)) }
+ tracing_info = true
+ end
+
+ local function trace_info(message, where, what)
+ trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) }
+ end
+
+ local function trace_node(what)
+ local nt = nodecodes[getid(what)]
+ local tl = trace_list[#trace_list]
+ if tl and tl[1] == "node" then
+ trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) }
+ else
+ trace_list[#trace_list+1] = { "node", nt }
+ end
+ end
+
+ local function show_tracing(head)
+ if tracing_info then
+ after = nodes_to_string(head)
+ for i=1,#trace_list do
+ local tag, text = unpack(trace_list[i])
+ if tag == "info" then
+ report_collapser(text)
+ else
+ report_collapser(" %s: %s",tag,text)
+ end
+ end
+ report_collapser("before: %s",before)
+ report_collapser("after : %s",after)
+ end
+ end
+
+ local function trace_done(str,data)
+ if getid(data) == penalty_code then
+ trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getpenalty(data)) }
+ else
+ trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getwidth(data)) }
+ end
+ tracing_info = true
+ end
+
+ local function forced_skip(head,current,width,where,trace) -- looks old ... we have other tricks now
+ if head == current then
+ if getsubtype(head) == baselineskip_code then
+ width = width - getwidth(head)
+ end
+ end
+ if width == 0 then
+ -- do nothing
+ elseif where == "after" then
+ head, current = insert_node_after(head,current,new_rule(w,h,d))
+ head, current = insert_node_after(head,current,new_kern(width))
+ head, current = insert_node_after(head,current,new_rule(w,h,d))
+ else
+ local c = current
+ head, current = insert_node_before(head,current,new_rule(w,h,d))
+ head, current = insert_node_before(head,current,new_kern(width))
+ head, current = insert_node_before(head,current,new_rule(w,h,d))
+ current = c
+ end
+ if trace then
+ report_vspacing("inserting forced skip of %p",width)
+ end
+ return head, current
+ end
+
+ -- penalty only works well when before skip
+
+ local discard = categories.discard
+ local largest = categories.largest
+ local force = categories.force
+ local penalty = categories.penalty
+ local add = categories.add
+ local disable = categories.disable
+ local nowhite = categories.nowhite
+ local goback = categories.goback
+ local packed = categories.packed
+ local overlay = categories.overlay
+ local enable = categories.enable
+ local notopskip = categories.notopskip
+
+ -- [whatsits][hlist][glue][glue][penalty]
+
+ local special_penalty_min = 32250
+ local special_penalty_max = 35000
+ local special_penalty_xxx = 0
+
+ -- this is rather messy and complex: we want to make sure that successive
+ -- header don't break but also make sure that we have at least a decent
+ -- break when we have succesive ones (often when testing)
+
+ -- todo: mark headers as such so that we can recognize them
+
+ local specialmethods = { }
+ local specialmethod = 1
+
+ specialmethods[1] = function(pagehead,pagetail,start,penalty)
+ --
+ if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then
+ return
+ end
+ local current = pagetail
+ --
+ -- nodes.showsimplelist(pagehead,0)
+ --
+ if trace_specials then
+ report_specials("checking penalty %a",penalty)
+ end
+ while current do
+ local id = getid(current)
+ if id == penalty_code then
+ local p = properties[current]
+ if p then
+ local p = p.special_penalty
+ if not p then
+ if trace_specials then
+ report_specials(" regular penalty, continue")
+ end
+ elseif p == penalty then
+ if trace_specials then
+ report_specials(" context penalty %a, same level, overloading",p)
+ end
+ return special_penalty_xxx
+ elseif p > special_penalty_min and p < special_penalty_max then
+ if penalty < p then
+ if trace_specials then
+ report_specials(" context penalty %a, lower level, overloading",p)
+ end
+ return special_penalty_xxx
+ else
+ if trace_specials then
+ report_specials(" context penalty %a, higher level, quitting",p)
+ end
+ return
+ end
+ elseif trace_specials then
+ report_specials(" context penalty %a, higher level, continue",p)
+ end
+ else
+ local p = getpenalty(current)
+ if p < 10000 then
+ -- assume some other mechanism kicks in so we seem to have content
+ if trace_specials then
+ report_specials(" regular penalty %a, quitting",p)
+ end
+ break
+ else
+ if trace_specials then
+ report_specials(" regular penalty %a, continue",p)
+ end
+ end
+ end
+ end
+ current = getprev(current)
+ end
+ -- none found, so no reson to be special
+ if trace_specials then
+ if pagetail then
+ report_specials(" context penalty, discarding, nothing special")
+ else
+ report_specials(" context penalty, discarding, nothing preceding")
+ end
+ end
+ return special_penalty_xxx
+ end
+
+ -- This will be replaced after 0.80+ when we have a more robust look-back and
+ -- can look at the bigger picture.
+
+ -- todo: look back and when a special is there before a list is seen penalty keep ut
+
+ -- we now look back a lot, way too often
+
+ -- userskip
+ -- lineskip
+ -- baselineskip
+ -- parskip
+ -- abovedisplayskip
+ -- belowdisplayskip
+ -- abovedisplayshortskip
+ -- belowdisplayshortskip
+ -- topskip
+ -- splittopskip
+
+ -- we could inject a vadjust to force a recalculation .. a mess
+ --
+ -- So, the next is far from robust and okay but for the moment this overlaying
+ -- has to do. Always test this with the examples in spac-ver.mkvi!
+
+ local function snap_topskip(current,method)
+ local w = getwidth(current)
+ setwidth(current,0)
+ return w, 0
+ end
+
+ local function check_experimental_overlay(head,current)
+ local p = nil
+ local c = current
+ local n = nil
+ local function overlay(p,n,mvl)
+ local p_wd, p_ht, p_dp = getwhd(p)
+ local n_wd, n_ht, n_dp = getwhd(n)
+ local skips = 0
+ --
+ -- We deal with this at the tex end .. we don't see spacing .. enabling this code
+ -- is probably harmless but then we need to test it.
+ --
+ -- we could calculate this before we call
+ --
+ -- problem: prev list and next list can be unconnected
+ --
+ local c = getnext(p)
+ local l = c
+ while c and c ~= n do
+ local id = getid(c)
+ if id == glue_code then
+ skips = skips + getwidth(c)
+ elseif id == kern_code then
+ skips = skips + getkern(c)
+ end
+ l = c
+ c = getnext(c)
+ end
+ local c = getprev(n)
+ while c and c ~= n and c ~= l do
+ local id = getid(c)
+ if id == glue_code then
+ skips = skips + getwidth(c)
+ elseif id == kern_code then
+ skips = skips + getkern(c)
+ end
+ c = getprev(c)
+ end
+ --
+ local delta = n_ht + skips + p_dp
+ texsetdimen("global","d_spac_overlay",-delta) -- for tracing
+ -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak
+ local k = new_kern(-delta)
+ head = insert_node_before(head,n,k)
+ if n_ht > p_ht then
+ local k = new_kern(n_ht-p_ht)
+ head = insert_node_before(head,p,k)
+ end
+ if trace_vspacing then
+ report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta)
+ end
+ return remove_node(head,current,true)
+ end
+
+ -- goto next line
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code or id == kern_code then
+ -- skip (actually, remove)
+ c = getnext(c)
+ elseif id == hlist_code then
+ n = c
+ break
+ else
+ break
+ end
+ end
+ if n then
+ -- we have a next line, goto prev line
+ c = current
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code then -- kern ?
+ c = getprev(c)
+ elseif id == hlist_code then
+ p = c
+ break
+ else
+ break
+ end
+ end
+ if not p then
+ if a_snapmethod == a_snapvbox then
+ -- quit, we're not on the mvl
+ else
+ -- inefficient when we're at the end of a page
+ local c = tonut(texlists.page_head)
+ while c and c ~= n do
+ local id = getid(c)
+ if id == hlist_code then
+ p = c
+ end
+ c = getnext(c)
+ end
+ if p and p ~= n then
+ return overlay(p,n,true)
+ end
+ end
+ elseif p ~= n then
+ return overlay(p,n,false)
+ end
+ end
+ -- in fact, we could try again later ... so then no remove (a few tries)
+ return remove_node(head,current,true)
+ end
+
+ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail
+ if trace then
+ reset_tracing(head)
+ end
+ local current = head
+ local oldhead = head
+ local glue_order = 0
+ local glue_data
+ local force_glue = false
+ local penalty_order = 0
+ local penalty_data
+ local natural_penalty
+ local special_penalty
+ local parskip
+ local ignore_parskip = false
+ local ignore_following = false
+ local ignore_whitespace = false
+ local keep_together = false
+ local lastsnap
+ local pagehead
+ local pagetail
+ --
+ -- todo: keep_together: between headers
+ --
+ local function getpagelist()
+ if not pagehead then
+ pagehead = texlists.page_head
+ if pagehead then
+ pagehead = tonut(pagehead)
+ pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet
+ end
+ end
+ end
+ --
+ local function compensate(n)
+ local g = 0
+ while n and getid(n) == glue_code do
+ g = g + getwidth(n)
+ n = getnext(n)
+ end
+ if n then
+ local p = getprop(n,"snapper")
+ if p then
+ local extra = p.extra
+ if extra and extra < 0 then -- hm, extra can be unset ... needs checking
+ local h = p.ch -- getheight(n)
+ -- maybe an extra check
+ -- if h - extra < g then
+ setheight(n,h-2*extra)
+ p.extra = 0
+ if trace_vsnapping then
+ report_snapper("removed extra space at top: %p",extra)
+ end
+ -- end
+ end
+ end
+ return n
+ end
+ end
+ --
+ local function removetopsnap()
+ getpagelist()
+ if pagehead then
+ local n = pagehead and compensate(pagehead)
+ if n and n ~= pagetail then
+ local p = getprop(pagetail,"snapper")
+ if p then
+ local e = p.extra
+ if e and e < 0 then
+ local t = texget("pagetotal")
+ if t > 0 then
+ local g = texget("pagegoal") -- 1073741823 is signal
+ local d = g - t
+ if d < -e then
+ local penalty = new_penalty(1000000)
+ setlink(penalty,head)
+ head = penalty
+ report_snapper("force pagebreak due to extra space at bottom: %p",e)
+ end
+ end
+ end
+ end
+ end
+ elseif head then
+ compensate(head)
+ end
+ end
+ --
+ local function getavailable()
+ getpagelist()
+ if pagehead then
+ local t = texget("pagetotal")
+ if t > 0 then
+ local g = texget("pagegoal")
+ return g - t
+ end
+ end
+ return false
+ end
+ --
+ local function flush(why)
+ if penalty_data then
+ local p = new_penalty(penalty_data)
+ if trace then
+ trace_done("flushed due to " .. why,p)
+ end
+ if penalty_data >= 10000 then -- or whatever threshold?
+ local prev = getprev(current)
+ if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue
+ -- tricky case: spacing/grid-007.tex: glue penalty glue
+ head = insert_node_before(head,prev,p)
+ else
+ head = insert_node_before(head,current,p)
+ end
+ else
+ head = insert_node_before(head,current,p)
+ end
+ -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
+ local props = properties[p]
+ if props then
+ props.special_penalty = special_penalty or penalty_data
+ else
+ properties[p] = {
+ special_penalty = special_penalty or penalty_data
+ }
+ end
+ -- end
+ end
+ if glue_data then
+ if force_glue then
+ if trace then
+ trace_done("flushed due to forced " .. why,glue_data)
+ end
+ head = forced_skip(head,current,getwidth(glue_data,width),"before",trace)
+ flush_node(glue_data)
+ else
+ local width, stretch, shrink = getglue(glue_data)
+ if width ~= 0 then
+ if trace then
+ trace_done("flushed due to non zero " .. why,glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ elseif stretch ~= 0 or shrink ~= 0 then
+ if trace then
+ trace_done("flushed due to stretch/shrink in" .. why,glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ else
+ -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w)
+ flush_node(glue_data)
+ end
+ end
+ end
+
+ if trace then
+ trace_node(current)
+ end
+ glue_order, glue_data, force_glue = 0, nil, false
+ penalty_order, penalty_data, natural_penalty = 0, nil, nil
+ parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false
+ end
+ --
+ if trace_vsnapping then
+ report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p",
+ texgetdimen("globalbodyfontstrutheight"),
+ texgetdimen("globalbodyfontstrutdepth"),
+ texgetdimen("bodyfontstrutheight"),
+ texgetdimen("bodyfontstrutdepth")
+ )
+ end
+ if trace then
+ trace_info("start analyzing",where,what)
+ end
+ if snap and where == "page" then
+ removetopsnap()
+ end
+ while current do
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code then
+ -- needs checking, why so many calls
+ if snap then
+ lastsnap = nil
+ local list = getlist(current)
+ local s = getattr(current,a_snapmethod)
+ if not s then
+ -- if trace_vsnapping then
+ -- report_snapper("mvl list not snapped")
+ -- end
+ elseif s == 0 then
+ if trace_vsnapping then
+ report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list))
+ end
+ else
+ local sv = snapmethods[s]
+ if sv then
+ -- check if already snapped
+ local done = list and already_done(id,list,a_snapmethod)
+ if done then
+ -- assume that the box is already snapped
+ if trace_vsnapping then
+ local w, h, d = getwhd(current)
+ report_snapper("mvl list already snapped at (%p,%p): %s",h,d,listtoutf(list))
+ end
+ else
+ local h, d, ch, cd, lines, extra = snap_hlist("mvl",current,sv,false,false)
+ lastsnap = {
+ ht = h,
+ dp = d,
+ ch = ch,
+ cd = cd,
+ extra = extra,
+ current = current,
+ }
+ setprop(current,"snapper",lastsnap)
+ if trace_vsnapping then
+ report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
+ nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list))
+ end
+ end
+ elseif trace_vsnapping then
+ report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list))
+ end
+ setattr(current,a_snapmethod,0)
+ end
+ else
+ --
+ end
+ -- tex.prevdepth = 0
+ flush("list")
+ current = getnext(current)
+ elseif id == penalty_code then
+ -- natural_penalty = getpenalty(current)
+ -- if trace then
+ -- trace_done("removed penalty",current)
+ -- end
+ -- head, current = remove_node(head,current,true)
+ current = getnext(current)
+ elseif id == kern_code then
+ if snap and trace_vsnapping and getkern(current) ~= 0 then
+ report_snapper("kern of %p kept",getkern(current))
+ end
+ flush("kern")
+ current = getnext(current)
+ elseif id == glue_code then
+ local subtype = getsubtype(current)
+ if subtype == userskip_code then
+ local sc, so, sp = getattrs(current,a_skipcategory,a_skiporder,a_skippenalty)
+ if not so then
+ so = 1 -- the others have no default value
+ end
+ if sp and sc == penalty then
+ if where == "page" then
+ getpagelist()
+ local p = specialmethods[specialmethod](pagehead,pagetail,current,sp)
+ if p then
+ -- todo: other tracer
+ --
+ -- if trace then
+ -- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod)
+ -- end
+ special_penalty = sp
+ sp = p
+ end
+ end
+ if not penalty_data then
+ penalty_data = sp
+ elseif penalty_order < so then
+ penalty_order, penalty_data = so, sp
+ elseif penalty_order == so and sp > penalty_data then
+ penalty_data = sp
+ end
+ if trace then
+ trace_skip("penalty in skip",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ elseif not sc then -- if not sc then
+ if glue_data then
+ if trace then
+ trace_done("flush",glue_data)
+ end
+ head = insert_node_before(head,current,glue_data)
+ if trace then
+ trace_natural("natural",current)
+ end
+ current = getnext(current)
+ glue_data = nil
+ else
+ -- not look back across head
+ -- todo: prev can be whatsit (latelua)
+ local previous = getprev(current)
+ if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then
+ local pwidth, pstretch, pshrink, pstretch_order, pshrink_order = getglue(previous)
+ local cwidth, cstretch, cshrink, cstretch_order, cshrink_order = getglue(current)
+ if pstretch_order == 0 and pshrink_order == 0 and cstretch_order == 0 and cshrink_order == 0 then
+ setglue(previous,pwidth + cwidth, pstretch + cstretch, pshrink + cshrink)
+ if trace then
+ trace_natural("removed",current)
+ end
+ head, current = remove_node(head,current,true)
+ if trace then
+ trace_natural("collapsed",previous)
+ end
+ else
+ if trace then
+ trace_natural("filler",current)
+ end
+ current = getnext(current)
+ end
+ else
+ if trace then
+ trace_natural("natural (no prev)",current)
+ end
+ current = getnext(current)
+ end
+ end
+ glue_order = 0
+ elseif sc == disable or sc == enable then
+ local next = getnext(current)
+ if next then
+ ignore_following = sc == disable
+ if trace then
+ trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ else
+ current = next
+ end
+ elseif sc == packed then
+ if trace then
+ trace_skip("packed",sc,so,sp,current)
+ end
+ -- can't happen !
+ head, current = remove_node(head,current,true)
+ elseif sc == nowhite then
+ local next = getnext(current)
+ if next then
+ ignore_whitespace = true
+ head, current = remove_node(head,current,true)
+ else
+ current = next
+ end
+ elseif sc == discard then
+ if trace then
+ trace_skip("discard",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ elseif sc == overlay then
+ -- todo (overlay following line over previous
+ if trace then
+ trace_skip("overlay",sc,so,sp,current)
+ end
+ -- beware: head can actually be after the affected nodes as
+ -- we look back ... some day head will the real head
+ head, current = check_experimental_overlay(head,current,a_snapmethod)
+ elseif ignore_following then
+ if trace then
+ trace_skip("disabled",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ elseif not glue_data then
+ if trace then
+ trace_skip("assign",sc,so,sp,current)
+ end
+ glue_order = so
+ head, current, glue_data = remove_node(head,current)
+ elseif glue_order < so then
+ if trace then
+ trace_skip("force",sc,so,sp,current)
+ end
+ glue_order = so
+ flush_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ elseif glue_order == so then
+ -- is now exclusive, maybe support goback as combi, else why a set
+ if sc == largest then
+ local cw = getwidth(current)
+ local gw = getwidth(glue_data)
+ if cw > gw then
+ if trace then
+ trace_skip("largest",sc,so,sp,current)
+ end
+ flush_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ else
+ if trace then
+ trace_skip("remove smallest",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ end
+ elseif sc == goback then
+ if trace then
+ trace_skip("goback",sc,so,sp,current)
+ end
+ flush_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ elseif sc == force then
+ -- last one counts, some day we can provide an accumulator and largest etc
+ -- but not now
+ if trace then
+ trace_skip("force",sc,so,sp,current)
+ end
+ flush_node(glue_data)
+ head, current, glue_data = remove_node(head,current)
+ elseif sc == penalty then
+ if trace then
+ trace_skip("penalty",sc,so,sp,current)
+ end
+ flush_node(glue_data)
+ glue_data = nil
+ head, current = remove_node(head,current,true)
+ elseif sc == add then
+ if trace then
+ trace_skip("add",sc,so,sp,current)
+ end
+ local cwidth, cstretch, cshrink = getglue(current)
+ local gwidth, gstretch, gshrink = getglue(glue_data)
+ setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink)
+ -- toto: order
+ head, current = remove_node(head,current,true)
+ else
+ if trace then
+ trace_skip("unknown",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ end
+ else
+ if trace then
+ trace_skip("unknown",sc,so,sp,current)
+ end
+ head, current = remove_node(head,current,true)
+ end
+ if sc == force then
+ force_glue = true
+ end
+ elseif subtype == lineskip_code then
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ setwidth(current,0)
+ if trace_vsnapping then
+ report_snapper("lineskip set to zero")
+ end
+ else
+ if trace then
+ trace_skip("lineskip",sc,so,sp,current)
+ end
+ flush("lineskip")
+ end
+ else
+ if trace then
+ trace_skip("lineskip",sc,so,sp,current)
+ end
+ flush("lineskip")
+ end
+ current = getnext(current)
+ elseif subtype == baselineskip_code then
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ setwidth(current,0)
+ if trace_vsnapping then
+ report_snapper("baselineskip set to zero")
+ end
+ else
+ if trace then
+ trace_skip("baselineskip",sc,so,sp,current)
+ end
+ flush("baselineskip")
+ end
+ else
+ if trace then
+ trace_skip("baselineskip",sc,so,sp,current)
+ end
+ flush("baselineskip")
+ end
+ current = getnext(current)
+ elseif subtype == parskip_code then
+ -- parskip always comes later
+ if ignore_whitespace then
+ if trace then
+ trace_natural("ignored parskip",current)
+ end
+ head, current = remove_node(head,current,true)
+ elseif glue_data then
+ local w = getwidth(current)
+ if w ~= 0 and w > getwidth(glue_data) then
+flush_node(glue_data)
+ glue_data = current
+ if trace then
+ trace_natural("taking parskip",current)
+ end
+ head, current = remove_node(head,current)
+ else
+ if trace then
+ trace_natural("removed parskip",current)
+ end
+ head, current = remove_node(head,current,true)
+ end
+ else
+ if trace then
+ trace_natural("honored parskip",current)
+ end
+ head, current, glue_data = remove_node(head,current)
+ end
+ elseif subtype == topskip_code or subtype == splittopskip_code then
+ local next = getnext(current)
+ if next and getattr(next,a_skipcategory) == notopskip then
+ nuts.setglue(current) -- zero
+ end
+ if snap then
+ local s = getattr(current,a_snapmethod)
+ if s and s ~= 0 then
+ setattr(current,a_snapmethod,0)
+ local sv = snapmethods[s]
+ local w, cw = snap_topskip(current,sv)
+ if trace_vsnapping then
+ report_snapper("topskip snapped from %p to %p for %a",w,cw,where)
+ end
+ else
+ if trace then
+ trace_skip("topskip",sc,so,sp,current)
+ end
+ flush("topskip")
+ end
+ else
+ if trace then
+ trace_skip("topskip",sc,so,sp,current)
+ end
+ flush("topskip")
+ end
+ current = getnext(current)
+ elseif subtype == abovedisplayskip_code and remove_math_skips then
+ --
+ if trace then
+ trace_skip("above display skip (normal)",sc,so,sp,current)
+ end
+ flush("above display skip (normal)")
+ current = getnext(current)
+ --
+ elseif subtype == belowdisplayskip_code and remove_math_skips then
+ --
+ if trace then
+ trace_skip("below display skip (normal)",sc,so,sp,current)
+ end
+ flush("below display skip (normal)")
+ current = getnext(current)
+ --
+ elseif subtype == abovedisplayshortskip_code and remove_math_skips then
+ --
+ if trace then
+ trace_skip("above display skip (short)",sc,so,sp,current)
+ end
+ flush("above display skip (short)")
+ current = getnext(current)
+ --
+ elseif subtype == belowdisplayshortskip_code and remove_math_skips then
+ --
+ if trace then
+ trace_skip("below display skip (short)",sc,so,sp,current)
+ end
+ flush("below display skip (short)")
+ current = getnext(current)
+ --
+ else -- other glue
+ if snap and trace_vsnapping then
+ local w = getwidth(current)
+ if w ~= 0 then
+ report_snapper("glue %p of type %a kept",w,gluecodes[subtype])
+ end
+ end
+ if trace then
+ trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current)
+ end
+ flush("some glue")
+ current = getnext(current)
+ end
+ else
+ flush(trace and formatters["node with id %a"](id) or "other node")
+ current = getnext(current)
+ end
+ end
+ if trace then
+ trace_info("stop analyzing",where,what)
+ end
+ -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then
+ -- penalty_data = natural_penalty
+ -- end
+ if trace and (glue_data or penalty_data) then
+ trace_info("start flushing",where,what)
+ end
+ local tail
+ if penalty_data then
+ tail = find_node_tail(head)
+ local p = new_penalty(penalty_data)
+ if trace then
+ trace_done("result",p)
+ end
+ setlink(tail,p)
+ -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
+ local props = properties[p]
+ if props then
+ props.special_penalty = special_penalty or penalty_data
+ else
+ properties[p] = {
+ special_penalty = special_penalty or penalty_data
+ }
+ end
+ -- end
+ end
+ if glue_data then
+ if not tail then tail = find_node_tail(head) end
+ if trace then
+ trace_done("result",glue_data)
+ end
+ if force_glue then
+ head, tail = forced_skip(head,tail,getwidth(glue_data),"after",trace)
+ flush_node(glue_data)
+ glue_data = nil
+ elseif tail then
+ setlink(tail,glue_data)
+setnext(glue_data)
+ else
+ head = glue_data
+ end
+ texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler
+ end
+ if trace then
+ if glue_data or penalty_data then
+ trace_info("stop flushing",where,what)
+ end
+ show_tracing(head)
+ if oldhead ~= head then
+ trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)])
+ end
+ end
+ return head
+ end
+
+ local stackhead, stacktail, stackhack = nil, nil, false
+
+ local function report(message,where,lst)
+ if lst and where then
+ report_vspacing(message,where,count_nodes(lst,true),nodeidstostring(lst))
+ else
+ report_vspacing(message,count_nodes(lst,true),nodeidstostring(lst))
+ end
+ end
+
+ -- ugly code: we get partial lists (check if this stack is still okay) ... and we run
+ -- into temp nodes (sigh)
+
+ local forceflush = false
+
+ function vspacing.pagehandler(newhead,where)
+ if newhead then
+ local newtail = find_node_tail(newhead) -- best pass that tail, known anyway
+ local flush = false
+ stackhack = true -- todo: only when grid snapping once enabled
+ -- todo: fast check if head = tail
+ for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes
+ if id ~= glue_code then
+ flush = true
+ elseif subtype == userskip_code then
+ if getattr(n,a_skipcategory) then
+ stackhack = true
+ else
+ flush = true
+ end
+ elseif subtype == parskip_code then
+ -- if where == new_graf then ... end
+ if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then
+ -- texsetcount("c_spac_vspacing_ignore_parskip",0)
+ setglue(n)
+ -- maybe removenode
+ end
+ end
+ end
+ texsetcount("c_spac_vspacing_ignore_parskip",0)
+
+ if forceflush then
+ forceflush = false
+ flush = true
+ end
+
+ if flush then
+ if stackhead then
+ if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end
+ setlink(stacktail,newhead)
+ newhead = stackhead
+ stackhead = nil
+ stacktail = nil
+ end
+ if stackhack then
+ stackhack = false
+ if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end
+ newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
+ else
+ if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end
+ end
+ return newhead
+ else
+ if stackhead then
+ if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end
+ setlink(stacktail,newhead)
+ else
+ if trace_collect_vspacing then report("%s > storing %s nodes in stack (initial): %s",where,newhead) end
+ stackhead = newhead
+ end
+ stacktail = newtail
+ end
+ end
+ return nil
+ end
+
+ function vspacing.pageoverflow()
+ local h = 0
+ if stackhead then
+ for n, id in nextnode, stackhead do
+ if id == glue_code then
+ h = h + getwidth(n)
+ elseif id == kern_code then
+ h = h + getkern(n)
+ end
+ end
+ end
+ return h
+ end
+
+ function vspacing.forcepageflush()
+ forceflush = true
+ end
+
+ local ignore = table.tohash {
+ "split_keep",
+ "split_off",
+ -- "vbox",
+ }
+
+ function vspacing.vboxhandler(head,where)
+ if head and not ignore[where] and getnext(head) then
+ if getnext(head) then -- what if a one liner and snapping?
+ head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
+ return head
+ end
+ end
+ return head
+ end
+
+ function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod
+ local box = getbox(n)
+ if box then
+ local list = getlist(box)
+ if list then
+ list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)
+ if aslist then
+ setlist(box,list) -- beware, dimensions of box are wrong now
+ else
+ setlist(box,vpack_node(list))
+ end
+ end
+ end
+ end
+
+end
+
+-- This one is needed to prevent bleeding of prevdepth to the next page
+-- which doesn't work well with forced skips. I'm not that sure if the
+-- following is a good way out.
+
+do
+
+ local outer = texnest[0]
+
+ local enabled = true
+ local trace = false
+ local report = logs.reporter("vspacing")
+
+ trackers.register("vspacing.synchronizepage",function(v)
+ trace = v
+ end)
+
+ directives.register("vspacing.synchronizepage",function(v)
+ enabled = v
+ end)
+
+ local ignoredepth = -65536000
+
+ -- A previous version analyzed the number of lines moved to the next page in
+ -- synchronizepage because prevgraf is unreliable in that case. However, we cannot
+ -- tweak that parameter because it is also used in postlinebreak and hangafter, so
+ -- there is a danger for interference. Therefore we now do it dynamically.
+
+ -- We can also support other lists but there prevgraf probably is ok.
+
+ function vspacing.getnofpreviouslines(head)
+ if enabled then
+ if not thead then
+ head = texlists.page_head
+ end
+ local noflines = 0
+ if head then
+ local tail = find_node_tail(tonut(head))
+ while tail do
+ local id = getid(tail)
+ if id == hlist_code then
+ if getsubtype(tail) == linelist_code then
+ noflines = noflines + 1
+ else
+ break
+ end
+ elseif id == vlist_code then
+ break
+ elseif id == glue_code then
+ local subtype = getsubtype(tail)
+ if subtype == baselineskip_code or subtype == lineskip_code then
+ -- we're ok
+ elseif subtype == parskip_code then
+ if getwidth(tail) > 0 then
+ break
+ else
+ -- we assume we're ok
+ end
+ end
+ elseif id == penalty_code then
+ -- we're probably ok
+ elseif id == rule_code or id == kern_code then
+ break
+ else
+ -- ins, mark, boundary, whatsit
+ end
+ tail = getprev(tail)
+ end
+ end
+ return noflines
+ end
+ end
+
+ interfaces.implement {
+ name = "getnofpreviouslines",
+ public = true,
+ actions = vspacing.getnofpreviouslines,
+ }
+
+ function vspacing.synchronizepage()
+ if enabled then
+ if trace then
+ local newdepth = outer.prevdepth
+ local olddepth = newdepth
+ if not texlists.page_head then
+ newdepth = ignoredepth
+ texset("prevdepth",ignoredepth)
+ outer.prevdepth = ignoredepth
+ end
+ report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth)
+ -- report("list %s",nodes.idsandsubtypes(head))
+ else
+ if not texlists.page_head then
+ texset("prevdepth",ignoredepth)
+ outer.prevdepth = ignoredepth
+ end
+ end
+ end
+ end
+
+ local trace = false
+ local last = nil
+ local vmode_code = tex.modelevels.vertical
+ local temp_code = nodecodes.temp
+ local getnest = tex.getnest
+ local getlist = tex.getlist
+
+ trackers.register("vspacing.forcestrutdepth",function(v) trace = v end)
+
+ -- abs : negative is inner
+
+ function vspacing.checkstrutdepth(depth)
+ local nest = getnest()
+ if abs(nest.mode) == vmode_code and nest.head then
+ local tail = nest.tail
+ local id = tail.id
+ if id == hlist_code then
+ if tail.depth < depth then
+ tail.depth = depth
+ end
+ nest.prevdepth = depth
+ elseif id == temp_code and getnest("ptr") == 0 then
+ local head = getlist("page_head")
+ if head then
+ tail = nodes.tail(head)
+ if tail and tail.id == hlist_code then
+ if tail.depth < depth then
+ tail.depth = depth
+ end
+ nest.prevdepth = depth
+ -- only works in lmtx
+ texset("pagedepth",depth)
+ end
+ end
+ end
+ end
+ end
+
+ interfaces.implement {
+ name = "checkstrutdepth",
+ arguments = "dimension",
+ actions = vspacing.checkstrutdepth,
+ }
+
+ function vspacing.forcestrutdepth(n,depth,trace_mode,plus)
+ local box = texgetbox(n)
+ if box then
+ box = tonut(box)
+ local head = getlist(box)
+ if head then
+ local tail = find_node_tail(head)
+ if tail then
+ if getid(tail) == hlist_code then
+ local dp = getdepth(tail)
+ if dp < depth then
+ setdepth(tail,depth)
+ outer.prevdepth = depth
+ if trace or trace_mode > 0 then
+ nuts.setvisual(tail,"depth")
+ end
+ end
+ end
+ last = nil
+ if plus then
+ -- penalty / skip ...
+ local height = 0
+ local sofar = 0
+ local same = false
+ local seen = false
+ local list = { }
+ last = nil
+ while tail do
+ local id = getid(tail)
+ if id == hlist_code or id == vlist_code then
+ local w, h, d = getwhd(tail)
+ height = height + h + d + sofar
+ sofar = 0
+ last = tail
+ elseif id == kern_code then
+ sofar = sofar + getkern(tail)
+ elseif id == glue_code then
+ if seen then
+ sofar = sofar + getwidth(tail)
+ seen = false
+ else
+ break
+ end
+ elseif id == penalty_code then
+ local p = getpenalty(tail)
+ if p >= 10000 then
+ same = true
+ seen = true
+ else
+ break
+ end
+ else
+ break
+ end
+ tail = getprev(tail)
+ end
+ texsetdimen("global","d_spac_prevcontent",same and height or 0)
+ end
+ end
+ end
+ end
+ end
+
+ function vspacing.pushatsame()
+ -- needs better checking !
+ if last then -- setsplit
+ nuts.setnext(getprev(last))
+ nuts.setprev(last)
+ end
+ end
+
+ function vspacing.popatsame()
+ -- needs better checking !
+ nuts.write(last)
+ end
+
+end
+
+-- interface
+
+do
+
+ -- old variant
+
+ implement {
+ name = "vspacing",
+ actions = vspacing.analyze,
+ scope = "private",
+ arguments = "string"
+ }
+
+ -- new variant
+
+ interfaces.implement {
+ name = "injectvspacing",
+ actions = vspacing.inject,
+ arguments = { "integer", "string" },
+ }
+
+ interfaces.implement {
+ name = "injectvpenalty",
+ actions = vspacing.injectpenalty,
+ arguments = "integer",
+ }
+
+ interfaces.implement {
+ name = "injectvskip",
+ actions = vspacing.injectskip,
+ arguments = "dimension",
+ }
+
+ interfaces.implement {
+ name = "injectdisable",
+ actions = vspacing.injectdisable,
+ }
+
+ --
+
+ implement {
+ name = "synchronizepage",
+ actions = vspacing.synchronizepage,
+ scope = "private"
+ }
+
+ implement {
+ name = "forcestrutdepth",
+ arguments = { "integer", "dimension", "integer" },
+ actions = vspacing.forcestrutdepth,
+ scope = "private"
+ }
+
+ implement {
+ name = "forcestrutdepthplus",
+ arguments = { "integer", "dimension", "integer", true },
+ actions = vspacing.forcestrutdepth,
+ scope = "private"
+ }
+
+ implement {
+ name = "pushatsame",
+ actions = vspacing.pushatsame,
+ scope = "private"
+ }
+
+ implement {
+ name = "popatsame",
+ actions = vspacing.popatsame,
+ scope = "private"
+ }
+
+ implement {
+ name = "vspacingsetamount",
+ actions = vspacing.setskip,
+ scope = "private",
+ arguments = "string",
+ }
+
+ implement {
+ name = "vspacingdefine",
+ actions = vspacing.setmap,
+ scope = "private",
+ arguments = "2 strings",
+ }
+
+ implement {
+ name = "vspacingcollapse",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = "integer"
+ }
+
+ implement {
+ name = "vspacingcollapseonly",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = { "integer", true }
+ }
+
+ implement {
+ name = "vspacingsnap",
+ actions = vspacing.snapbox,
+ scope = "private",
+ arguments = { "integer", "integer" }
+ }
+
+ implement {
+ name = "definesnapmethod",
+ actions = vspacing.definesnapmethod,
+ scope = "private",
+ arguments = "2 strings",
+ }
+
+ -- local remove_node = nodes.remove
+ -- local find_node_tail = nodes.tail
+ --
+ -- interfaces.implement {
+ -- name = "fakenextstrutline",
+ -- actions = function()
+ -- local head = texlists.page_head
+ -- if head then
+ -- local head = remove_node(head,find_node_tail(head),true)
+ -- texlists.page_head = head
+ -- buildpage()
+ -- end
+ -- end
+ -- }
+
+ implement {
+ name = "removelastline",
+ actions = function()
+ local head = texlists.page_head
+ if head then
+ local tail = find_node_tail(head)
+ if tail then
+ -- maybe check for hlist subtype 1
+ local head = remove_node(head,tail,true)
+ texlists.page_head = head
+ buildpage()
+ end
+ end
+ end
+ }
+
+ implement {
+ name = "showpagelist", -- will improve
+ actions = function()
+ local head = texlists.page_head
+ if head then
+ print("start")
+ while head do
+ print(" " .. tostring(head))
+ head = head.next
+ end
+ end
+ end
+ }
+
+ implement {
+ name = "pageoverflow",
+ actions = { vspacing.pageoverflow, context }
+ }
+
+ implement {
+ name = "forcepageflush",
+ actions = vspacing.forcepageflush
+ }
+
+end
diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua
index 2f0d54227..2fc926321 100644
--- a/tex/context/base/mkiv/spac-ver.lua
+++ b/tex/context/base/mkiv/spac-ver.lua
@@ -185,7 +185,7 @@ local glue_code = nodecodes.glue
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local rule_code = nodecodes.rule
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local userskip_code = gluecodes.userskip
local lineskip_code = gluecodes.lineskip
@@ -293,7 +293,7 @@ end
local function validvbox(parentid,list)
if parentid == hlist_code then
local id = getid(list)
- if id == localpar_code and start_of_par(list) then
+ if id == par_code and start_of_par(list) then
list = getnext(list)
if not next then
return nil
@@ -329,7 +329,7 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only
-- problem: any snapped vbox ends up in a line
if list and parentid == hlist_code then
local id = getid(list)
- if id == localpar_code and start_of_par(list) then
+ if id == par_code and start_of_par(list) then
list = getnext(list)
if not list then
return false
@@ -1263,7 +1263,7 @@ do
end
end
-- in fact, we could try again later ... so then no remove (a few tries)
- return remove_node(head, current, true)
+ return remove_node(head,current,true)
end
local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail
@@ -1501,7 +1501,7 @@ do
-- if trace then
-- trace_done("removed penalty",current)
-- end
- -- head, current = remove_node(head, current, true)
+ -- head, current = remove_node(head,current,true)
current = getnext(current)
elseif id == kern_code then
if snap and trace_vsnapping and getkern(current) ~= 0 then
@@ -1539,7 +1539,7 @@ do
if trace then
trace_skip("penalty in skip",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif not sc then -- if not sc then
if glue_data then
if trace then
@@ -1562,7 +1562,7 @@ do
if trace then
trace_natural("removed",current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
if trace then
trace_natural("collapsed",previous)
end
@@ -1587,7 +1587,7 @@ do
if trace then
trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
else
current = next
end
@@ -1596,12 +1596,12 @@ do
trace_skip("packed",sc,so,sp,current)
end
-- can't happen !
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif sc == nowhite then
local next = getnext(current)
if next then
ignore_whitespace = true
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
else
current = next
end
@@ -1609,7 +1609,7 @@ do
if trace then
trace_skip("discard",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif sc == overlay then
-- todo (overlay following line over previous
if trace then
@@ -1622,20 +1622,20 @@ do
if trace then
trace_skip("disabled",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif not glue_data then
if trace then
trace_skip("assign",sc,so,sp,current)
end
glue_order = so
- head, current, glue_data = remove_node(head, current)
+ head, current, glue_data = remove_node(head,current)
elseif glue_order < so then
if trace then
trace_skip("force",sc,so,sp,current)
end
glue_order = so
flush_node(glue_data)
- head, current, glue_data = remove_node(head, current)
+ head, current, glue_data = remove_node(head,current)
elseif glue_order == so then
-- is now exclusive, maybe support goback as combi, else why a set
if sc == largest then
@@ -1651,7 +1651,7 @@ do
if trace then
trace_skip("remove smallest",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
end
elseif sc == goback then
if trace then
@@ -1666,34 +1666,34 @@ do
trace_skip("force",sc,so,sp,current)
end
flush_node(glue_data)
- head, current, glue_data = remove_node(head, current)
+ head, current, glue_data = remove_node(head,current)
elseif sc == penalty then
if trace then
trace_skip("penalty",sc,so,sp,current)
end
flush_node(glue_data)
glue_data = nil
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif sc == add then
if trace then
trace_skip("add",sc,so,sp,current)
end
local cwidth, cstretch, cshrink = getglue(current)
local gwidth, gstretch, gshrink = getglue(glue_data)
- setglue(old,gwidth + cwidth, gstretch + cstretch, gshrink + cshrink)
+ setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink)
-- toto: order
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
else
if trace then
trace_skip("unknown",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
end
else
if trace then
trace_skip("unknown",sc,so,sp,current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
end
if sc == force then
force_glue = true
@@ -1748,7 +1748,7 @@ do
if trace then
trace_natural("ignored parskip",current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
elseif glue_data then
local w = getwidth(current)
if (w ~= 0) and (w > getwidth(glue_data)) then
@@ -1756,18 +1756,18 @@ do
if trace then
trace_natural("taking parskip",current)
end
- head, current = remove_node(head, current)
+ head, current = remove_node(head,current)
else
if trace then
trace_natural("removed parskip",current)
end
- head, current = remove_node(head, current, true)
+ head, current = remove_node(head,current,true)
end
else
if trace then
trace_natural("honored parskip",current)
end
- head, current, glue_data = remove_node(head, current)
+ head, current, glue_data = remove_node(head,current)
end
elseif subtype == topskip_code or subtype == splittopskip_code then
local next = getnext(current)
@@ -1902,18 +1902,6 @@ do
return head
end
- -- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display
- -- \par -> vmode_par
- --
- -- status.best_page_break
- -- tex.lists.best_page_break
- -- tex.lists.best_size (natural size to best_page_break)
- -- tex.lists.least_page_cost (badness of best_page_break)
- -- tex.lists.page_head
- -- tex.lists.contrib_head
-
- -- do
-
local stackhead, stacktail, stackhack = nil, nil, false
local function report(message,where,lst)
@@ -1930,7 +1918,6 @@ do
local forceflush = false
function vspacing.pagehandler(newhead,where)
- -- local newhead = texlists.contrib_head
if newhead then
local newtail = find_node_tail(newhead) -- best pass that tail, known anyway
local flush = false
@@ -1972,11 +1959,9 @@ do
if stackhack then
stackhack = false
if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end
- -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
else
if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end
- -- texlists.contrib_head = newhead
end
return newhead
else
@@ -1993,20 +1978,6 @@ do
return nil
end
- -- function vspacing.flushpagestack()
- -- if stackhead then
- -- local head = texlists.contrib_head
- -- if head then
- -- local tail = find_node_tail(head)
- -- setlink(tail,stackhead)
- -- else
- -- texlists.contrib_head = tonode(stackhead)
- -- end
- -- stackhead, stacktail = nil, nil
- -- end
- --
- -- end
-
function vspacing.pageoverflow()
local h = 0
if stackhead then
@@ -2187,6 +2158,8 @@ do
tail.depth = depth
end
nest.prevdepth = depth
+ -- only works in lmtx
+ texset("pagedepth",depth)
end
end
end
diff --git a/tex/context/base/mkiv/spac-ver.mkiv b/tex/context/base/mkiv/spac-ver.mkiv
index 2c8c30bec..680ba7a99 100644
--- a/tex/context/base/mkiv/spac-ver.mkiv
+++ b/tex/context/base/mkiv/spac-ver.mkiv
@@ -1940,7 +1940,7 @@
\clf_vspacingsetamount{#1}}
\def\spac_vspacing_no_topskip % use grouped
- {\c_attr_skipcategory\plusten}
+ {\c_attr_skipcategory\pluseleven}
% \installcorenamespace{vspacingamountnormal}
% \installcorenamespace{vspacingamountgrid}
diff --git a/tex/context/base/mkiv/spac-ver.mkxl b/tex/context/base/mkiv/spac-ver.mkxl
index c76c011e1..7a4688791 100644
--- a/tex/context/base/mkiv/spac-ver.mkxl
+++ b/tex/context/base/mkiv/spac-ver.mkxl
@@ -15,7 +15,7 @@
\unprotect
-\registerctxluafile{spac-ver}{optimize}
+\registerctxluafile{spac-ver}{autosuffix,optimize}
% todo: use usernodes ?
@@ -64,7 +64,7 @@
\def\skipfactor {.75}
\def\skipgluefactor{.25}
-\def\normalskipamount
+\permanent\def\normalskipamount
{\openlineheight
\ifgridsnapping \orelse \ifconditional\c_spac_whitespace_flexible
\s!plus \skipgluefactor\openlineheight
@@ -76,7 +76,7 @@
\let\bodyfontinterlinespace\empty
\fi
-\unexpanded\def\presetnormallineheight % each bodyfont
+\permanent\protected\def\presetnormallineheight % each bodyfont
{\edef\normallineheight{\interlinespaceparameter\c!line}%
\iflocalinterlinespace \else
\edef\m_spac_normallineheight{\bodyfontinterlinespace}%
@@ -85,7 +85,7 @@
\fi
\fi}
-\unexpanded\def\setupspecifiedinterlinespace[#1]%
+\permanent\protected\def\setupspecifiedinterlinespace[#1]%
{\setupcurrentinterlinespace[#1]%
\spac_linespacing_setup_specified_interline_space}
@@ -125,7 +125,7 @@
{\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
\spacing\currentrelativeinterlinespace}}
-\unexpanded\def\setuprelativeinterlinespace[#1]%
+\permanent\protected\def\setuprelativeinterlinespace[#1]%
{\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace}
\def\spac_linespacing_setup_relative_interlinespace#1%
@@ -140,7 +140,7 @@
\spacing\currentrelativeinterlinespace
\fi}
-\unexpanded\def\spac_linespacing_setup_use
+\protected\def\spac_linespacing_setup_use
{\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname
\let\currentinterlinespace\m_spac_interlinespace
\spac_linespacing_setup_specified_interline_space
@@ -148,7 +148,7 @@
% we only support named interlinespaces
\fi}
-\unexpanded\def\useinterlinespaceparameter#1% see footnotes
+\permanent\protected\def\useinterlinespaceparameter#1% see footnotes
{\edef\m_spac_interlinespace{#1\c!interlinespace}%
\ifempty\m_spac_interlinespace \else
\spac_linespacing_setup_use
@@ -165,18 +165,12 @@
\installmacrostack\currentinterlinespace
-\unexpanded\def\setupinterlinespace
- {\dodoubleempty\spac_linespacing_setup}
-
-\ifdefined\setupinterlinespace_double \else
- \let\setupinterlinespace_double\setup_interlinespace % for a while
-\fi
-
-\def\spac_linespacing_setup[#1][#2]%
- {\settrue\interlinespaceisset % reset has to be done when needed
- \ifsecondargument
- \setupinterlinespace_double[#1][#2]%
- \orelse\iffirstargument
+\permanent\overloaded\tolerant\protected\def\setupinterlinespace[#1]#*[#2]%
+ {\ifarguments
+ \settrue\interlinespaceisset
+ \spac_linespacing_synchronize_local
+ \or
+ \settrue\interlinespaceisset
\ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname
\edef\currentinterlinespace{#1}%
\spac_linespacing_setup_specified_interline_space
@@ -184,9 +178,9 @@
\else
\spac_linespacing_setup_specified_or_relative[#1]%
\fi
- \else
- \let\currentinterlinespace\empty
- \spac_linespacing_synchronize_local
+ \or
+ \settrue\interlinespaceisset
+ \setup_interlinespace[#1][#2]%
\fi}
\def\spac_linespacing_setup_specified_or_relative[#1]%
@@ -200,7 +194,7 @@
\the\everysetuplocalinterlinespace
\localinterlinespacefalse}
-\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain
+\permanent\protected\def\dosetupcheckedinterlinespace#1% often a chain
{\edef\p_spac_checked_interlinespace{#1}%
\ifempty\p_spac_checked_interlinespace
\spac_linespacing_synchronize_local
@@ -228,7 +222,7 @@
\fi
\fi}
-\unexpanded\def\setuplocalinterlinespace[#1]%
+\permanent\protected\def\setuplocalinterlinespace[#1]%
{\localinterlinespacetrue
\push_macro_currentinterlinespace
\setupinterlinespace[#1]%
@@ -244,8 +238,8 @@
\newcount\c_spac_spacefactor
\newdimen\d_spac_prevcontent % set by lua
-\unexpanded\def\removelastskip
- {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+% \permanent\overloaded\protected\def\removelastskip
+% {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
\def\doifoutervmode
{\ifvmode
@@ -258,7 +252,7 @@
\expandafter\gobbleoneargument
\fi}
-\unexpanded\def\dosomebreak#1%
+\protected\def\dosomebreak#1%
{\doifoutervmode
{\s_spac_lastskip\lastskip
\removelastskip
@@ -269,19 +263,19 @@
\vskip\s_spac_lastskip
\fi}}
-\unexpanded\def\packed
+\permanent\protected\def\packed
{\nointerlineskip}
-\unexpanded\def\godown[#1]%
+\permanent\protected\def\godown[#1]%
{\relax
\ifhmode\endgraf\fi
\ifvmode\nointerlineskip\vskip#1\relax\fi}
-\unexpanded\def\smallskip{\vskip\smallskipamount}
-\unexpanded\def\medskip {\vskip\medskipamount}
-\unexpanded\def\bigskip {\vskip\bigskipamount}
+\permanent\protected\def\smallskip{\vskip\smallskipamount}
+\permanent\protected\def\medskip {\vskip\medskipamount}
+\permanent\protected\def\bigskip {\vskip\bigskipamount}
-\unexpanded\def\smallbreak
+\permanent\protected\def\smallbreak
{\par
\ifvmode\ifdim\lastskip<\smallskipamount
\removelastskip
@@ -289,7 +283,7 @@
\smallskip
\fi\fi}
-\unexpanded\def\medbreak
+\permanent\protected\def\medbreak
{\par
\ifvmode\ifdim\lastskip<\medskipamount
\removelastskip
@@ -297,7 +291,7 @@
\medskip
\fi\fi}
-\unexpanded\def\bigbreak
+\permanent\protected\def\bigbreak
{\par
\ifvmode\ifdim\lastskip<\bigskipamount
\removelastskip
@@ -305,18 +299,18 @@
\bigskip
\fi\fi}
-\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode
-\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
-\unexpanded\def\allowbreak{\penalty \zerocount} % can be hmode or vmode
+\permanent\protected\def\break {\penalty-\plustenthousand} % can be hmode or vmode
+\permanent\protected\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
+\permanent\protected\def\allowbreak{\penalty \zerocount} % can be hmode or vmode
-\unexpanded\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode
-\unexpanded\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode
+\permanent\protected\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode
+\permanent\protected\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode
%D Made slightly more readable:
-\unexpanded\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=}
-\unexpanded\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=}
-\unexpanded\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi}
+\permanent\protected\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=}
+\permanent\protected\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=}
+\permanent\protected\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi}
\def\spac_helpers_vglue_indeed
{\par
@@ -338,9 +332,13 @@
%D We adapt plain's \type {\removelastskip} a bit:
-\unexpanded\def\removelastskip % also in supp-box
+\pushoverloadmode
+
+\permanent\overloaded\protected\def\removelastskip % also in supp-box
{\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+\popoverloadmode
+
% The whitespace handler. We could cache settings but normally there are not
% that many in a set.
@@ -353,8 +351,31 @@
%def\v_spac_whitespace_current{\zeropoint}
\let\v_spac_whitespace_current\v!none
-\unexpanded\def\setupwhitespace
- {\doifelsenextoptionalcs\spac_whitespace_setup_yes\spac_whitespace_setup_nop}
+% \permanent\tolerant\protected\def\setupwhitespace[#1]%
+% {\ifarguments
+% \spac_whitespace_setup_nop
+% \or
+% \spac_whitespace_setup_yes{#1}%
+% \fi}
+%
+% \def\spac_whitespace_setup_yes#1%
+% {\edef\m_spac_whitespace_asked{#1}%
+% \ifempty\m_spac_whitespace_asked
+% \spac_whitespace_setup_nop
+% \else
+% \let\v_spac_whitespace_current\m_spac_whitespace_asked
+% \spac_whitespace_setup
+% \fi}
+
+\permanent\tolerant\protected\def\setupwhitespace[#1]%
+ {\ifarguments
+ \spac_whitespace_setup_nop
+ \orelse\iftok{#1}\emptytoks
+ \spac_whitespace_setup_nop
+ \else
+ \edef\v_spac_whitespace_current{#1}%
+ \spac_whitespace_setup
+ \fi}
\def\spac_whitespace_setup_nop
{\ifx\v_spac_whitespace_current\v!none\else
@@ -363,15 +384,6 @@
\let\synchronizewhitespace\spac_whitespace_setup_nop
-\def\spac_whitespace_setup_yes[#1]%
- {\edef\m_spac_whitespace_asked{#1}%
- \ifempty\m_spac_whitespace_asked
- \spac_whitespace_setup_nop
- \else
- \let\v_spac_whitespace_current\m_spac_whitespace_asked
- \spac_whitespace_setup
- \fi}
-
\def\spac_whitespace_setup % quick test for no list
{\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
\lastnamedcs
@@ -407,7 +419,7 @@
\fi
\fi}
-\unexpanded\def\installwhitespacemethod#1#2%
+\permanent\protected\def\installwhitespacemethod#1#2%
{\setvalue{\??whitespacemethod#1}{#2}}
\installwhitespacemethod \v!fix {}
@@ -431,7 +443,7 @@
\s_spac_whitespace_parskip#1\fi
\relax}
-\unexpanded\def\forgetparskip
+\permanent\protected\def\forgetparskip
{\s_spac_whitespace_parskip\zeropoint
\parskip\zeropoint
\let\v_spac_whitespace_current\v!none}
@@ -445,8 +457,8 @@
% \def\spac_whitespace_setup_method#1%
% {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
-\unexpanded\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
-\unexpanded\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]}
+\permanent\protected\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
+\permanent\protected\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]}
\setupwhitespace
[\v!none]
@@ -458,10 +470,7 @@
\newconditional\c_spac_packed_blank \settrue\c_spac_packed_blank
\newcount \c_spac_packed_level
-\unexpanded\def\startpacked
- {\dosingleempty\spac_packed_start}
-
-\def\spac_packed_start[#1]% nesting afvangen
+\permanent\tolerant\protected\def\startpacked[#1]%
{\global\advance\c_spac_packed_level\plusone
\par
\ifnum\c_spac_packed_level=\plusone \ifvmode
@@ -472,18 +481,18 @@
\setupwhitespace[\v!none]% or \forgetparskip
\fi \fi}
-\unexpanded\def\stoppacked
+\permanent\protected\def\stoppacked
{\par
\ifnum\c_spac_packed_level=\plusone \ifvmode
\endgroup
\fi \fi
\global\advance\c_spac_packed_level\minusone}
-\unexpanded\def\startunpacked
+\permanent\protected\def\startunpacked
{\directdefaultvspacing % \blank
\begingroup}
-\unexpanded\def\stopunpacked
+\permanent\protected\def\stopunpacked
{\endgroup
\directdefaultvspacing}% \blank}
@@ -500,8 +509,8 @@
\installtextracker
{linecorrection.boxes}
- {\let\spac_lines_vbox\ruledvbox}
- {\let\spac_lines_vbox\vbox}
+ {\letfrozen\let\spac_lines_vbox\ruledvbox}
+ {\letfrozen\let\spac_lines_vbox\vbox}
\let\v_spac_lines_around_action_set\relax
\let\m_spac_lines_around \empty
@@ -517,20 +526,14 @@
\ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi
\endcsname}
-\unexpanded\def\startlinecorrection
- {\endgraf
- \begingroup
- \setconstant\c_spac_lines_correction_mode\plusone
- \dosingleempty\spac_lines_start_correction}
+\permanent\tolerant\protected\def\startlinecorrection [#1]{\spac_lines_start_correction\plusone{#1}}
+\permanent\tolerant\protected\def\startlocallinecorrection[#1]{\spac_lines_start_correction\plustwo{#1}}
-\unexpanded\def\startlocallinecorrection
+\protected\def\spac_lines_start_correction#1#2%
{\endgraf
\begingroup
- \setconstant\c_spac_lines_correction_mode\plustwo
- \dosingleempty\spac_lines_start_correction}
-
-\unexpanded\def\spac_lines_start_correction[#1]%
- {\edef\m_spac_lines_around{#1}%
+ \setconstant\c_spac_lines_correction_mode#1%
+ \edef\m_spac_lines_around{#2}%
\spac_lines_action_around
\d_spac_prevdepth\prevdepth
\spac_lines_initialize_corrections
@@ -548,7 +551,7 @@
\fi
\ignorespaces}
-\unexpanded\def\spac_lines_stop_correction
+\protected\def\spac_lines_stop_correction
{\removeunwantedspaces
\egroup
\ifgridsnapping
@@ -558,14 +561,14 @@
\fi
\endgroup}
-\unexpanded\def\spac_lines_stop_correction_ongrid
+\protected\def\spac_lines_stop_correction_ongrid
{\directcheckedvspacing\v!white % \blank[\v!white]%
\spac_lines_action_around
\snaptogrid\hpack{\box\scratchbox}%
\directcheckedvspacing\v!white
\spac_lines_action_around}
-\unexpanded\def\spac_lines_stop_correction_normal
+\protected\def\spac_lines_stop_correction_normal
{\directcheckedvspacing\v!nowhite % \blank[\v!nowhite]%
\ifdim\parskip>\zeropoint
% too fuzzy otherwise
@@ -616,16 +619,16 @@
% todo:
-\unexpanded\def\correctwhitespace
+\permanent\protected\def\correctwhitespace
{\dowithnextboxcs\correctwhitespacefinish\vbox}
-\unexpanded\def\correctwhitespacefinish
+\permanent\protected\def\correctwhitespacefinish
{\startbaselinecorrection
\flushnextbox
\stopbaselinecorrection}
-\unexpanded\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}}
-\unexpanded\def\horizontalstrut{\hpack {\strut}}
+\permanent\protected\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}}
+\permanent\protected\def\horizontalstrut{\hpack {\strut}}
%D Here follow some presets related to interline spacing and therefore also struts.
%D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used
@@ -700,19 +703,19 @@
\def\normalizedbodyfontsize{12pt}
\fi
-\unexpanded\def\topskipcorrection
+\permanent\protected\def\topskipcorrection
{\simpletopskipcorrection
\vskip-\struttotal
\verticalstrut}
-\unexpanded\def\simpletopskipcorrection
+\permanent\protected\def\simpletopskipcorrection
{\ifdim\topskip>\openstrutheight
% == \vskip\topskipgap
\vskip\topskip
\vskip-\openstrutheight
\fi}
-\unexpanded\def\settopskip % the extra test is needed for the lbr family
+\permanent\protected\def\settopskip % the extra test is needed for the lbr family
{\topskip
\ifgridsnapping
\zeropoint
@@ -735,24 +738,24 @@
\fi
\fi}
-\unexpanded\def\setmaxdepth
+\protected\def\setmaxdepth
{\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
\newskip \usedbaselineskip % These used to be \normal... but that isn't pretty
\newskip \usedlineskip % in the token interface, so thes few now have new
\newdimen\usedlineskiplimit % names. They are public but not really user commands.
-\unexpanded\def\normalbaselines
+\permanent\protected\def\normalbaselines
{\baselineskip \usedbaselineskip
\lineskip \usedlineskip
\lineskiplimit\usedlineskiplimit}
-\unexpanded\def\flexiblebaselines
+\permanent\protected\def\flexiblebaselines
{\baselineskip \usedbaselineskip
\lineskip 1\usedlineskip \s!plus 1\s!fill
\lineskiplimit\usedlineskiplimit}
-\unexpanded\def\setnormalbaselines
+\permanent\protected\def\setnormalbaselines % used in overload
{\ifdim\normallineheight>\zeropoint
\lineheight\normallineheight
\fi
@@ -779,7 +782,7 @@
\usedlineskiplimit\zeropoint\relax
\normalbaselines}
-\unexpanded\def\spacing#1% vertical
+\permanent\protected\def\spacing#1% vertical
{\ifgridsnapping
\let\spacingfactor\plusone
\else
@@ -790,10 +793,10 @@
\setnormalbaselines
\setstrut}
-% \unexpanded\def\forgetverticalstretch % \forgetspacing
+% \protected\def\forgetverticalstretch % \forgetspacing
% {\spacing\plusone}
-\unexpanded\def\forgetverticalstretch
+\permanent\protected\def\forgetverticalstretch
{\let\spacingfactor \plusone
\let\systemtopskipfactor \topskipfactor
\let\systemmaxdepthfactor\maxdepthfactor
@@ -812,8 +815,8 @@
\let\restoreinterlinespace\relax
-\unexpanded\def\saveinterlinespace
- {\unexpanded\edef\restoreinterlinespace
+\permanent\protected\def\saveinterlinespace
+ {\protected\edef\restoreinterlinespace
{\lineheight \the\lineheight
\openstrutheight \the\openstrutheight
\openstrutdepth \the\openstrutdepth
@@ -844,7 +847,7 @@
\def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
-% \unexpanded\def\strut
+% \protected\def\strut
% {\relax
% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
@@ -852,17 +855,17 @@
%D The double \type {\hbox} construction enables us to backtrack boxes.
-\let\strutht\undefined \newdimen\strutht
-\let\strutdp\undefined \newdimen\strutdp
+\overloaded\let\strutht\undefined \newdimen\strutht
+\overloaded\let\strutdp\undefined \newdimen\strutdp
-\unexpanded\def\setstrut
+\permanent\protected\def\setstrut
{\ifgridsnapping
\setstrutgridyes
\else
\setstrutgridnop
\fi}
-\unexpanded\def\setstrutgridyes
+\permanent\protected\def\setstrutgridyes
{\strutht\spacingfactor\dimexpr
\ifdim\minimumstrutheight>\zeropoint
\minimumstrutheight
@@ -879,7 +882,7 @@
\relax
\dosetstrut}
-\unexpanded\def\setstrutgridnop
+\permanent\protected\def\setstrutgridnop
{\strutht\spacingfactor\dimexpr
\ifdim\minimumstrutheight>\zeropoint
\minimumstrutheight
@@ -896,30 +899,30 @@
\relax
\dosetstrut}
-\unexpanded\def\setcharstrut#1%
+\permanent\protected\def\setcharstrut#1%
{\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps
\strutht\ht\strutbox
\strutdp\dp\strutbox
\dosetstrut}
-\unexpanded\def\settightstrut
+\permanent\protected\def\settightstrut
{\setcharstrut{(}}
-\unexpanded\def\setfontstrut
+\permanent\protected\def\setfontstrut
{\setcharstrut{(gplQT}}
-\unexpanded\def\setcapstrut% could be M, but Q has descender
+\permanent\protected\def\setcapstrut% could be M, but Q has descender
{\setcharstrut{Q}}
%D Handy for math (used in mathml):
-\unexpanded\def\charhtstrut
+\permanent\protected\def\charhtstrut
{\begingroup
\setcharstrut{GJY}%
\vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht
\endgroup}
-\unexpanded\def\chardpstrut
+\permanent\protected\def\chardpstrut
{\begingroup
\setcharstrut{gjy}%
\vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint
@@ -930,8 +933,8 @@
%D an attribute so far have shown that it's slower because testing the attribute
%D takes time too.
-\unexpanded\def\dosetstrut
- {\let\strut\normalstrut
+\permanent\protected\def\dosetstrut
+ {\enforced\let\strut\normalstrut
\ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo
% compensate rounding error /- 1sp to avoid too many
% 1sp baselineskips in for instance verbatim
@@ -1012,18 +1015,18 @@
\ht\strutbox\strutht
\dp\strutbox\strutdp}
-\unexpanded\def\strut % still callbacks for \hbox{\strut}
+\permanent\protected\def\strut % still callbacks for \hbox{\strut}
{\relax
\dontleavehmode
\copy\strutbox}
-% \unexpanded\def\strut % slightly faster
+% \protected\def\strut % slightly faster
% {\relax
% \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox}
\let\normalstrut\strut
-\unexpanded\def\halfstrut
+\permanent\protected\def\halfstrut
{\relax
\dontleavehmode
\begingroup
@@ -1033,7 +1036,7 @@
\box\scratchbox
\endgroup}
-\unexpanded\def\quarterstrut
+\permanent\protected\def\quarterstrut
{\relax
\dontleavehmode
\begingroup
@@ -1043,7 +1046,7 @@
\box\scratchbox
\endgroup}
-\unexpanded\def\depthstrut
+\permanent\protected\def\depthstrut
{\relax
\dontleavehmode
\begingroup
@@ -1052,7 +1055,7 @@
\box\scratchbox
\endgroup}
-\unexpanded\def\halflinestrut
+\permanent\protected\def\halflinestrut
{\relax
\dontleavehmode
\begingroup
@@ -1061,7 +1064,7 @@
\box\scratchbox
\endgroup}
-\unexpanded\def\noheightstrut
+\permanent\protected\def\noheightstrut
{\relax
\dontleavehmode
\begingroup
@@ -1084,10 +1087,7 @@
\installcorenamespace{struts}
-\unexpanded\def\setupstrut
- {\dosingleempty\spac_struts_setup}
-
-\def\spac_struts_setup[#1]%
+\permanent\tolerant\protected\def\setupstrut[#1]%
{\edef\m_strut{#1}%
\ifcsname\??struts\m_strut\endcsname
\lastnamedcs
@@ -1095,7 +1095,7 @@
\setcharstrut\m_strut
\fi}
-\unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal
+\permanent\protected\def\synchronizestrut#1% no [] parsing, faster for internal
{\edef\m_strut{#1}%
\ifcsname\??struts\m_strut\endcsname
\lastnamedcs
@@ -1103,38 +1103,38 @@
\setcharstrut\m_strut
\fi}
-\unexpanded\def\dosynchronizestrut#1% no [] parsing, faster for internal
+\permanent\protected\def\dosynchronizestrut#1% no [] parsing, faster for internal
{\ifcsname\??struts#1\endcsname
\lastnamedcs
\else
\setcharstrut{#1}%
\fi}
-\unexpanded\def\showstruts % adapts .. is wrong
+\permanent\protected\def\showstruts % adapts .. is wrong
{\c_strut_visual_mode\zerocount
\setteststrut
\settestcrlf}
-\unexpanded\def\showcolorstruts % adapts .. is wrong
+\permanent\protected\def\showcolorstruts % adapts .. is wrong
{\c_strut_visual_mode\plusone
\setteststrut
\settestcrlf}
-\unexpanded\def\setteststrut
+\permanent\protected\def\setteststrut
{\def\strutwidth{.8pt}%
\setstrut}
-\unexpanded\def\dontshowstruts
+\permanent\protected\def\dontshowstruts
{\unsetteststrut
\settestcrlf}
-\unexpanded\def\unsetteststrut
+\permanent\protected\def\unsetteststrut
{\let\strutwidth\zeropoint
\setstrut}
\def\autostrutfactor{1.1}
-\unexpanded\def\setautostrut
+\permanent\protected\def\setautostrut
{\begingroup
\setbox\scratchbox\copy\strutbox
\setstrut
@@ -1150,26 +1150,26 @@
\newtoks\everysetnostrut
-\unexpanded\def\setnostrut
+\permanent\protected\def\setnostrut
{\the\everysetnostrut}
\appendtoks
\setbox\strutbox\copy\nostrutbox
- \let\strut\empty
- \let\endstrut\empty
- \let\begstrut\empty
+ \enforced\let\strut \empty
+ \enforced\let\endstrut\empty
+ \enforced\let\begstrut\empty
\to \everysetnostrut
%D When enabled, sigstruts will remove themselves if nothing goes inbetween. For
%D practical reasons we define some boundary characters here.
-\unexpanded\def\leftboundary {\protrusionboundary\plusone}
-\unexpanded\def\rightboundary {\protrusionboundary\plustwo}
-\unexpanded\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals
+\permanent\protected\def\leftboundary {\protrusionboundary\plusone}
+\permanent\protected\def\rightboundary {\protrusionboundary\plustwo}
+\permanent\protected\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals
\newsignal\strutsignal \setfalse\sigstruts
-\unexpanded\def\begstrut
+\permanent\protected\def\begstrut
{\relax\ifcase\strutht
% \ignorespaces % maybe
\else
@@ -1198,7 +1198,7 @@
%\boundary\plusone
\hskip\zeropoint}
-\unexpanded\def\endstrut
+\permanent\protected\def\endstrut
{\relax\ifhmode
\ifcase\strutht
% \removeunwantedspaces % maybe
@@ -1251,13 +1251,13 @@
%
% so:
-\unexpanded\def\pseudostrut
+\permanent\protected\def\pseudostrut
{\noindent} % better: \dontleavehmode
\let\pseudobegstrut\pseudostrut
\let\pseudoendstrut\removeunwantedspaces
-\unexpanded\def\resetteststrut
+\permanent\protected\def\resetteststrut
{\def\strutwidth{\zeropoint}% no let
\setstrut}
@@ -1284,17 +1284,21 @@
%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for
%D instance the visual debugger.
-\unexpanded\def\offinterlineskip
+\pushoverloadmode
+
+\overloaded\permanent\protected\def\offinterlineskip
{\baselineskip-\thousandpoint
\lineskip \zeropoint
\lineskiplimit\maxdimen
% We also need this here now; thanks to taco for figuring that out!
\def\minimumlinedistance{\zeropoint}}
-\unexpanded\def\nointerlineskip
+\overloaded\permanent\protected\def\nointerlineskip
{\prevdepth-\thousandpoint}
-\let\normaloffinterlineskip\offinterlineskip % knuth's original
+\aliased\let\normaloffinterlineskip\offinterlineskip % knuth's original
+
+\popoverloadmode
%D This is tricky. The prevdepth value is still set to the last one even if there is
%D nothing on the page. The same is true for prevgraf, which doesn't resemble the
@@ -1312,19 +1316,19 @@
\let\getnofpreviouslines\!!zerocount
\fi
-\unexpanded\def\page_otr_synchronize_page_yes
+\protected\def\page_otr_synchronize_page_yes
{\aftergroup\page_otr_synchronize_page_indeed
- \glet\page_otr_synchronize_page\relax}
+ \global\enforced\let\page_otr_synchronize_page\relax}
-% \unexpanded\def\page_otr_synchronize_page_indeed
+% \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
-\unexpanded\def\page_otr_synchronize_page_indeed
+\protected\def\page_otr_synchronize_page_indeed
{\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi
- \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
+ \global\enforced\let\page_otr_synchronize_page\page_otr_synchronize_page_yes}
\let\page_otr_synchronize_page\page_otr_synchronize_page_yes
@@ -1334,18 +1338,20 @@
%D My own one:
-\unexpanded\def\spac_helpers_push_interlineskip_yes
- {\edef\oninterlineskip
+\protected\def\spac_helpers_push_interlineskip_yes
+ {\enforced\edef\oninterlineskip
{\baselineskip \the\baselineskip
\lineskip \the\lineskip
\lineskiplimit\the\lineskiplimit
\noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}%
- \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
+ \enforced\let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
-\unexpanded\def\spac_helpers_push_interlineskip_nop
- {\let\oninterlineskip\setnormalbaselines}
+\protected\def\spac_helpers_push_interlineskip_nop
+ {\enforced\let\oninterlineskip\setnormalbaselines}
-\unexpanded\def\offinterlineskip
+\pushoverloadmode
+
+\overloaded\permanent\protected\def\offinterlineskip
{\ifdim\baselineskip>\zeropoint
\spac_helpers_push_interlineskip_yes
\else
@@ -1353,14 +1359,16 @@
\fi
\normaloffinterlineskip}
-\let\oninterlineskip\relax
+\permanent\let\oninterlineskip\relax
+
+\popoverloadmode
-\unexpanded\def\resetpenalties#1%
+\permanent\protected\def\resetpenalties#1%
{\ifdefined#1%
\frozen#1\minusone
\fi}
-\unexpanded\def\setpenalties#1#2#3%
+\permanent\protected\def\setpenalties#1#2#3%
{\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text
\frozen#1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax
\fi}
@@ -1376,16 +1384,16 @@
\newcount\c_spac_keep_lines_together
\let\restoreinterlinepenalty\relax
-\unexpanded\def\spac_penalties_restore
- {\glet\restoreinterlinepenalty\relax
- \global\resetpenalties\interlinepenalties
+\protected\def\spac_penalties_restore
+ {\global\enforced\let\restoreinterlinepenalty\relax
+ \overloaded\global\resetpenalties\interlinepenalties
\global\c_spac_keep_lines_together\zerocount}
-\unexpanded\def\keeplinestogether#1%
+\protected\def\keeplinestogether#1%
{\ifnum#1>\c_spac_keep_lines_together
\global\c_spac_keep_lines_together#1%
- \global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
- \glet\restoreinterlinepenalty\spac_penalties_restore
+ \overloaded\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
+ \global\enforced\let\restoreinterlinepenalty\spac_penalties_restore
\fi}
\def\defaultdisplaywidowpenalty {50}
@@ -1404,7 +1412,7 @@
\def\defaultgridfinalhyphendemerits {5000} % always was so
\def\defaultgridadjdemerits {10000} % always was so
-\unexpanded\def\nopenalties
+\permanent\protected\def\nopenalties
{\frozen\widowpenalty \zerocount
\frozen\clubpenalty \zerocount
\frozen\brokenpenalty \zerocount
@@ -1412,7 +1420,7 @@
\frozen\finalhyphendemerits \zerocount
\frozen\adjdemerits \zerocount}
-\unexpanded\def\setdefaultpenalties
+\permanent\protected\def\setdefaultpenalties
{\directsetup{\systemsetupsprefix\s!default}}
\startsetups [\systemsetupsprefix\s!reset]
@@ -1472,8 +1480,8 @@
\newbox\b_spac_struts_saved
-\unexpanded\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox}
-\unexpanded\def\savedstrut{\copy \b_spac_struts_saved}
+\permanent\protected\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox}
+\permanent\protected\def\savedstrut{\copy \b_spac_struts_saved}
%D Good old blank redone:
@@ -1499,8 +1507,8 @@
\newdimen \globalbodyfontstrutheight
\newdimen \globalbodyfontstrutdepth
-\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi}
-\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi}
+\permanent\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi}
+\permanent\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi}
\def\spac_grids_set_local_snapping#1%
{\ifgridsnapping
@@ -1516,7 +1524,7 @@
\lastnamedcs\else#1%
\fi}}
-\unexpanded\def\installsnapvalues#1#2%
+\permanent\protected\def\installsnapvalues#1#2%
{\let\m_spac_snapper\empty
\rawprocesscommacommand[#2]\spac_grids_expand_snapper
\edef\currentsnapper{#1:\m_spac_snapper}%
@@ -1529,9 +1537,9 @@
\setevalue{\??gridsnappers#1}{\c_attr_snapmethod\the\scratchcounter\relax}%
\letvalue{\??gridsnappersets#1}\m_spac_snapper}
-\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals
+\permanent\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals
-\unexpanded\def\usegridparameter#1% no checking here
+\permanent\protected\def\usegridparameter#1% no checking here
{\edef\m_spac_grid_asked{#1\c!grid}%
\ifempty\m_spac_grid_asked
\c_attr_snapvbox\attributeunsetvalue
@@ -1540,10 +1548,7 @@
\c_attr_snapvbox\c_attr_snapmethod
\fi}
-\unexpanded\def\definegridsnapping
- {\dodoubleargument\spac_grids_define}
-
-\def\spac_grids_define[#1][#2]%
+\permanent\tolerant\protected\def\definegridsnapping[#1]#*[#2]%
{\installsnapvalues{#1}{#2}}
\edef\spac_grids_snap_value_reset
@@ -1637,12 +1642,12 @@
\definegridsnapping[\v!math:-\v!line] [\v!math,-\v!line,\v!split]
\definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split]
-\unexpanded\def\synchronizelocallinespecs
+\permanent\protected\def\synchronizelocallinespecs
{\bodyfontlineheight \normallineheight
\bodyfontstrutheight\strutht
\bodyfontstrutdepth \strutdp}
-\unexpanded\def\synchronizegloballinespecs
+\permanent\protected\def\synchronizegloballinespecs
{\global\globalbodyfontlineheight \normallineheight
\global\globalbodyfontstrutheight\strutht
\global\globalbodyfontstrutdepth \strutdp}
@@ -1658,7 +1663,7 @@
%D We still have to synchronize these:
-\unexpanded\def\synchronizeskipamounts
+\permanent\protected\def\synchronizeskipamounts
{\bigskipamount
\skipfactor\baselineskip
\s!plus\skipgluefactor\baselineskip
@@ -1669,30 +1674,20 @@
%D Snapping.
-\newif\ifgridsnapping
-
-%unexpanded\def\moveongrid {\dosingleempty\spac_grids_move_on}
-\unexpanded\def\snaptogrid {\dosingleempty\spac_grids_snap_to}
-\unexpanded\def\placeongrid{\dosingleempty\spac_grids_place_on}
+% \newif\ifgridsnapping % already defined
-\unexpanded\def\startgridsnapping
- {\dosingleempty\spac_grids_start_snapping}
-
-\unexpanded\def\spac_grids_start_snapping[#1]%
+\permanent\tolerant\protected\def\startgridsnapping[#1]%
{\snaptogrid[#1]\vbox\bgroup}
-\unexpanded\def\stopgridsnapping
+\permanent\protected\def\stopgridsnapping
{\egroup}
-% \def\spac_grids_move_on[#1]%
-% {[obsolete]} % gone, unless we set an attribute
-
-\def\spac_grids_place_on[#1]%
+\permanent\tolerant\protected\def\placeongrid[#1]%
{\snaptogrid[#1]\vbox} % mark as done
-\def\spac_grids_snap_to[#1]% list or predefined
+\permanent\tolerant\protected\def\snaptogrid[#1]% list or predefined
{\ifgridsnapping
- \expandafter\spac_grids_snap_to_indeed
+ \expandafter\spac_grids_snap_to_indeed % todo: move inline
\else
\expandafter\gobbleoneargument
\fi{#1}}
@@ -1723,7 +1718,7 @@
\setsystemmode\v!grid
\spac_grids_snap_value_set\askedgridmode}
-\unexpanded\def\synchronizegridsnapping
+\protected\def\synchronizegridsnapping
{\edef\askedgridmode{\layoutparameter\c!grid}%
\ifx\askedgridmode\v!no % official
\spac_grids_check_nop
@@ -1735,10 +1730,10 @@
\spac_grids_check_yes
\fi}
-\unexpanded\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing)
+\permanent\protected\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing)
{\setlayoutparameter\c!grid{#1}\synchronizegridsnapping}
-\unexpanded\def\checkgridmethod#1%
+\permanent\protected\def\checkgridmethod#1%
{\edef\p_grid{#1}%
\ifempty\p_grid
\let\checkedgridmethod\empty
@@ -1753,7 +1748,7 @@
\fi
\fi}
-\unexpanded\def\applygridmethod#1#2#3% content localsettings (used in head rendering)
+\permanent\protected\def\applygridmethod#1#2#3% content localsettings (used in head rendering)
{\checkgridmethod{#1}%
\ifx\checkedgridscope\v!global
\ifempty\checkedgridmethod \else
@@ -1778,13 +1773,13 @@
\egroup
\fi}
-\unexpanded\gdef\page_layouts_calculate_overshoot
+\protected\gdef\page_layouts_calculate_overshoot
{\ifgridsnapping\ifcase\layoutlines
\getnoflines\textheight
\textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax
\fi\fi}
-\unexpanded\def\page_layouts_report_overshoot
+\protected\def\page_layouts_report_overshoot
{\page_layouts_calculate_overshoot
\ifdim\textovershoot>\zeropoint
\writestatus\m!layouts{gridmode,\space
@@ -1809,7 +1804,7 @@
three=blue,
four=gray]
-\unexpanded\def\setgridtracebox#1[#2]% % maybe reverse the order
+\permanent\protected\def\setgridtracebox#1[#2]% % maybe reverse the order
{\setbox\nextbox#1%
{\hbox
{\hbox to \zeropoint
@@ -1821,7 +1816,7 @@
\setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r
\setnewconstant\gridboxlinemode \plusone
-\unexpanded\def\gridboxvbox
+\permanent\protected\def\gridboxvbox
{\ifcase\gridboxlinemode
\vpack
\or
@@ -1834,9 +1829,9 @@
\ruledvpack
\fi}
-\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
+\permanent\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
-\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
+\permanent\protected\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
{\setbox#1\gridboxvbox to #3 % given size
{\forgetall
\resetvisualizers
@@ -1878,7 +1873,7 @@
%D Helper:
-\unexpanded\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
+\protected\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
{\doifelse{#2}\v!line
{#1\ifgridsnapping
\bodyfontlineheight
@@ -1921,21 +1916,20 @@
\installcorenamespace{vspacingamount}
-\unexpanded\def\definevspacingamount
- {\dotripleempty\spac_vspacing_define_amount}
-
-\def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
- {\ifthirdargument
- \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}%
- \orelse\ifsecondargument
- \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}%
- \else
+\permanent\tolerant\protected\def\definevspacingamount[#1]#*[#2]#*[#3]% can be combined
+ {\ifarguments
+ %setvalue{\??vspacingamount#1}{\lineheight}%
+ \or
\setvalue{\??vspacingamount#1}{\lineheight}%
+ \or
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}%
+ \or
+ \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}%
\fi
\clf_vspacingsetamount{#1}}
\def\spac_vspacing_no_topskip % use grouped
- {\c_attr_skipcategory\plusten}
+ {\c_attr_skipcategory\pluseleven}
% \installcorenamespace{vspacingamountnormal}
% \installcorenamespace{vspacingamountgrid}
@@ -1949,13 +1943,10 @@
% \csname g>#1\endcsname{#3}%
% \clf_vspacingsetamount{#1}}
-\unexpanded\def\definevspacing
- {\dodoubleempty\spac_vspacing_define}
-
-\def\spac_vspacing_define[#1][#2]%
+\permanent\tolerant\protected\def\definevspacing[#1]#*[#2]%
{\clf_vspacingdefine{#1}{#2}}
-%D The injector code (generated at the \LUA\ end):
+%D The injector code (generated at the \LUA\ end). This will go away!
\newtoks\everybeforeblankhandling
\newtoks\everyafterblankhandling
@@ -1985,34 +1976,34 @@
\relax
\to \everyafterblankhandling
-\unexpanded\def\setblankpacked
+\permanent\protected\def\setblankpacked
{\settrue\c_space_ignore_parskip}
-\unexpanded\def\setblankcategory#1%
+\permanent\protected\def\setblankcategory#1%
{\settrue\c_space_vspacing_done
\c_attr_skipcategory#1\relax}
-\unexpanded\def\setblankorder#1%
+\permanent\protected\def\setblankorder#1%
{\c_attr_skiporder#1\relax}
-\unexpanded\def\fixedblankskip
+\permanent\protected\def\fixedblankskip
{\settrue\c_space_vspacing_fixed}
-\unexpanded\def\flexibleblankskip
+\permanent\protected\def\flexibleblankskip
{\setfalse\c_space_vspacing_fixed}
-% \unexpanded\def\addblankskip#1#2#3%
+% \protected\def\addblankskip#1#2#3%
% {\settrue\c_space_vspacing_done
% \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
-\unexpanded\def\setblankpenalty#1%
+\permanent\protected\def\setblankpenalty#1%
{\flushblankhandling
\settrue\c_space_vspacing_done
\c_attr_skipcategory\plusthree
\c_attr_skippenalty #1\relax
\flushblankhandling}
-\unexpanded\def\startblankhandling % move this to \vspacing
+\permanent\protected\def\startblankhandling % move this to \vspacing
{\par
\ifvmode
\expandafter\dostartblankhandling
@@ -2020,16 +2011,16 @@
\expandafter\nostartblankhandling
\fi}
-\unexpanded\def\nostartblankhandling#1\stopblankhandling
+\permanent\protected\def\nostartblankhandling#1\stopblankhandling
{}
-\def\dostartblankhandling
+\permanent\def\dostartblankhandling
{\begingroup
\setfalse\c_space_vspacing_done
\setfalse\c_space_ignore_parskip
\the\everybeforeblankhandling}
-\unexpanded\def\stopblankhandling
+\permanent\protected\def\stopblankhandling
{\the\everyafterblankhandling
\ifconditional\c_space_vspacing_done
\vskip\s_spac_vspacing_temp
@@ -2040,30 +2031,37 @@
\endgroup
\fi}
-\unexpanded\def\flushblankhandling
+\permanent\protected\def\flushblankhandling
{\the\everyafterblankhandling
\ifconditional\c_space_vspacing_done
\vskip\s_spac_vspacing_temp
+ \setfalse\c_space_vspacing_done
\fi
- \setfalse\c_space_vspacing_done
\the\everybeforeblankhandling}
-\unexpanded\def\addpredefinedblankskip#1#2%
+\permanent\protected\def\addpredefinedblankskip#1#2%
{\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
-% \unexpanded\def\addpredefinedblankskip#1#2%
+% \protected\def\addpredefinedblankskip#1#2%
% {\settrue\c_space_vspacing_done
% \advance\s_spac_vspacing_temp#1\dimexpr\the\csname\ifgridsnapping g\else n\fi>#2\endcsname\relax}
-\unexpanded\def\addaskedblankskip#1#2%
+\permanent\protected\def\addaskedblankskip#1#2%
{\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr#2\relax}
% The main spacer:
-\unexpanded\def\vspacing
- {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop}
+% \protected\def\vspacing
+% {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop}
+
+\tolerant\protected\def\vspacing[#1]%
+ {\ifarguments
+ \spac_vspacing_yes[\currentvspacing]% in the new mechanism no [] needed
+ \else
+ \spac_vspacing_yes[#1]% in the new mechanism no [] needed
+ \fi}
\def\spac_vspacing_yes
{\ifinpagebody % somewhat weird
@@ -2097,7 +2095,7 @@
\installcorenamespace{vspacing}
-\unexpanded\def\directvspacing#1%
+\protected\def\directvspacing#1%
{\par
\ifchkdim#1\or
\spac_vspacing_dim_preset{\the\dimexpr#1}%
@@ -2131,14 +2129,14 @@
\directvspacing\currentvspacing
\fi}
-\def\directdefaultvspacing
+\permanent\protected\def\directdefaultvspacing
{\ifinpagebody % somewhat weird
\directvspacing\currentvspacing
\orelse\ifconditional\c_spac_packed_blank
\directvspacing\currentvspacing
\fi}
-\def\directcheckedvspacing
+\permanent\protected\def\directcheckedvspacing
{\ifinpagebody % somewhat weird
\expandafter\directvspacing
\orelse\ifconditional\c_spac_packed_blank
@@ -2147,7 +2145,7 @@
\expandafter\gobbleoneargument
\fi}
-\unexpanded\def\useblankparameter#1% faster local variant
+\permanent\protected\def\useblankparameter#1% faster local variant
{\edef\m_spac_blank_asked{#1\c!blank}%
\ifempty\m_spac_blank_asked\else
\directvspacing\m_spac_blank_asked
@@ -2155,7 +2153,7 @@
%D Handy (and faster):
-\unexpanded\def\directvpenalty#1%
+\permanent\protected\def\directvpenalty#1%
{\begingroup
\c_attr_skipcategory\plusthree
\c_attr_skippenalty #1\relax
@@ -2163,7 +2161,7 @@
\vskip\zeropoint
\endgroup}
-\unexpanded\def\directvskip#1%
+\permanent\protected\def\directvskip#1%
{\begingroup
\c_attr_skipcategory\plusone
\c_attr_skippenalty \attributeunsetvalue
@@ -2173,27 +2171,23 @@
%D These depend on bigskipamount cum suis so we'd better sync them:
-\unexpanded\def\setupvspacing
- {\doifelsenextoptionalcs\setupvspacing_yes\setupvspacing_nop}
-
\let\currentvspacing\s!default % hm, default, standard ...
-\def\setupvspacing_yes[#1]%
- {\edef\currentvspacing{#1}%
- \spac_whitespace_setup_nop % yes or no, was forgotten
- }
+\permanent\tolerant\protected\def\setupvspacing[#1]%
+ {\ifarguments\else
+ \edef\currentvspacing{#1}%
+ \fi
+ \synchronizevspacing}
-\def\setupvspacing_nop
+\permanent\protected\def\synchronizevspacing
{\ifempty\currentvspacing % mistakenly had an \else
\let\currentvspacing\s!default
\fi
\spac_whitespace_setup_nop}
-\unexpanded\def\restorestandardblank % or default ?
+\permanent\protected\def\restorestandardblank % or default ?
{\let\currentvspacing\v!standard}
-\let\synchronizevspacing\setupvspacing_nop
-
%D The \type {category:4} is default.
\definevspacingamount[\v!none] [\zeropoint] [\zeropoint]
@@ -2210,7 +2204,7 @@
\definevspacingamount[\v!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible
-\def\bodyfontwhitespace
+\permanent\def\bodyfontwhitespace
{\dimexpr
\ifzeropt\parskip
\zeropoint
@@ -2274,7 +2268,7 @@
% 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names
-\unexpanded\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m
+\protected\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m
{\begingroup
\scratchcounterone\numexpr\plusthree*#1+#2\relax
\scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax
@@ -2282,7 +2276,7 @@
\normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}%
\endgroup}
-\unexpanded\def\spac_vspacing_define_same_page#1%
+\protected\def\spac_vspacing_define_same_page#1%
{\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone
{\spac_vspacing_define_same_step\recurselevel\zerocount % before
\spac_vspacing_define_same_step\recurselevel\plusone % after
@@ -2311,12 +2305,12 @@
% We keep this one as reference
%
-% \unexpanded\def\inhibitblank
+% \protected\def\inhibitblank
% {\vspacing[\v!disable]}
%
% but use the following more efficient variant instead:
-\unexpanded\def\inhibitblank
+\permanent\protected\def\inhibitblank
{\ifvmode
\begingroup
\c_attr_skipcategory\plusfive
@@ -2337,30 +2331,27 @@
\installcorenamespace{vspace}
-\unexpanded\def\definevspace
- {\dotripleempty\spac_vspace_define}
-
-\def\spac_vspace_define[#1][#2][#3]%
- {\ifthirdargument
- \setvalue{\??vspace#1:#2}{#3}%
- \else
+\permanent\tolerant\protected\def\definevspace[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ \or
+ \letvalue{\??vspace:#1}\empty % or undefined?
+ \or
\setvalue{\??vspace:#1}{#2}%
+ \or
+ \setvalue{\??vspace#1:#2}{#3}%
\fi}
\letvalue{\??vspace:\s!unknown}\zeropoint
-\unexpanded\def\vspace
- {\dodoubleempty\spac_vspace_inject}
-
\def\spac_vspace_unknown
{\csname\??vspace:\s!unknown\endcsname}
-\def\spac_vspace_inject[#1][#2]% use \lastnamedcs
+\permanent\tolerant\protected\def\vspace[#1]#*[#2]%
{\par
\ifvmode
\removelastskip
\vskip
- \ifsecondargument
+ \ifparameter#2\or
\ifcsname\??vspace#1:#2\endcsname
\lastnamedcs
\orelse\ifcsname\??vspace:#2\endcsname
@@ -2368,7 +2359,7 @@
\else
\spac_vspace_unknown
\fi
- \orelse\iffirstargument
+ \orelse\ifparameter#1\or
\ifcsname\??vspace:#1\endcsname
\lastnamedcs
\else
@@ -2395,26 +2386,25 @@
\c!location=\v!left,
\c!n=\zerocount]
-\unexpanded\def\starthanging
- {\dontleavehmode\bgroup
- \dosingleempty\spac_hanging_start}
-
-\unexpanded\def\stophanging
- {\endgraf
- \egroup}
-
\let\m_spac_hanging_location\empty
-\def\spac_hanging_start[#1]%
- {\doifelseassignment{#1}
- {\let\m_spac_hanging_location\empty
- \setupcurrenthanging[#1]}%
- {\edef\m_spac_hanging_location{#1}}%
+\permanent\tolerant\protected\def\starthanging[#1]%
+ {\dontleavehmode\bgroup
+ \ifhastok={#1}%
+ \let\m_spac_hanging_location\empty
+ \setupcurrenthanging[#1]%
+ \else
+ \edef\m_spac_hanging_location{#1}%
+ \fi
\ifempty\m_spac_hanging_location
\edef\m_spac_hanging_location{\directhangingparameter\c!location}%
\fi
\dowithnextboxcs\spac_hanging_finish\hbox}
+\permanent\protected\def\stophanging
+ {\endgraf
+ \egroup}
+
\def\spac_hanging_finish
{\scratchdistance\directhangingparameter\c!distance\relax
\ifdim\ht\nextbox>\strutht
@@ -2440,7 +2430,6 @@
\fi
\ignorespaces}
-
%D \macros
%D {startfixed}
%D
@@ -2465,34 +2454,33 @@
\installcorenamespace{fixedalternatives}
-\unexpanded\def\startfixed
- {\bgroup
- \dosingleempty\typo_fixed_start}
+\let\stopfixed\relax
-\def\typo_fixed_start
- {\ifhmode
+\permanent\protected\def\startfixed
+ {\bgroup
+ \ifhmode
\expandafter\typo_fixed_start_h
\else
\expandafter\typo_fixed_start_v
\fi}
-\def\typo_fixed_start_h[#1]%
- {\let\stopfixed\typo_fixed_stop_h
+\tolerant\def\typo_fixed_start_h[#1]%
+ {\enforced\let\stopfixed\typo_fixed_stop_h
\dowithnextbox{\typo_fixed_finish{#1}}%
\vbox\bgroup
%ignorespaces
\setlocalhsize}
-\unexpanded\def\typo_fixed_stop_h
+\protected\def\typo_fixed_stop_h
{%removeunwantedspaces
\egroup
\egroup}
-\def\typo_fixed_start_v[#1]%
- {\let\stopfixed\typo_fixed_stop_v
+\tolerant\def\typo_fixed_start_v[#1]%
+ {\enforced\let\stopfixed\typo_fixed_stop_v
\startbaselinecorrection}
-\unexpanded\def\typo_fixed_stop_v
+\protected\def\typo_fixed_stop_v
{\stopbaselinecorrection
\egroup}
@@ -2503,7 +2491,7 @@
\letvalue{\??fixedalternatives\s!unknown}\tbox
\letvalue{\??fixedalternatives\s!default}\tbox
-\unexpanded\def\typo_fixed_finish#1%
+\protected\def\typo_fixed_finish#1%
{\expandnamespacevalue\??fixedalternatives{#1}\s!default{\box\nextbox}}
% %D Forgotten already:
@@ -2534,7 +2522,7 @@
%D Helper:
-\unexpanded\def\checkedblank[#1]%
+\permanent\protected\def\checkedblank[#1]%
{\edef\p_blank{#1}%
\ifempty\p_blank
% ignore
@@ -2550,7 +2538,7 @@
\newskip\prerolledblank
-\unexpanded\def\prerollblank[#1]%
+\permanent\protected\def\prerollblank[#1]%
{\begingroup
\edef\p_blank{#1}%
\ifempty\p_blank
@@ -2588,6 +2576,51 @@
% test \par
% test \par
-\unexpanded\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
+\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
+
+% experimental (for the moment only for hh and ws)
+
+%def\vspacingfromscratchtoks {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax}
+\def\vspacingpredefinedvalue#1{\scratchdimen\dimexpr\csname\??vspacingamount#1\endcsname\relax}
+%def\vspacingfromtempstring {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax}
+
+\let\spac_vspacing_yes_indeed_old\spac_vspacing_yes_indeed
+\let\spac_vspacing_nop_indeed_old\spac_vspacing_nop_indeed
+\let\directvspacing_old \directvspacing
+
+\def\spac_vspacing_yes_indeed_new[#1]%
+ {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi}
+
+\def\spac_vspacing_nop_indeed_new
+ {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\currentvspacing}\fi\fi}
+
+\protected\def\directvspacing_new#1%
+%{\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi}
+ {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\iftok{#1}\emptytoks\currentvspacing\else#1\fi}\fi\fi}
+
+\let\directvpenalty_old\directvpenalty
+\let\directvskip_old \directvskip
+\let\inhibitblank_old \inhibitblank
+
+\protected\def\directvpenalty_new#1{\ifmmode\else\par\ifvmode\clf_injectvpenalty#1\relax\fi\fi}
+\protected\def\directvskip_new #1{\ifmmode\else\par\ifvmode\clf_injectvskip #1\relax\fi\fi}
+\protected\def\inhibitblank_new {\ifmmode\else\par\ifvmode\clf_injectdisable \fi\fi}
+
+\installtexdirective
+ {vspacing.experimental}
+ {\writestatus{vspacing}{enabling experimental handler}%
+ \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_new
+ \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_new
+ \enforced\let\directvspacing\directvspacing_new
+ \enforced\let\directvpenalty\directvpenalty_new
+ \enforced\let\directvskip\directvskip_new
+ \enforced\let\inhibitblank\inhibitblank_new}
+ {\writestatus{vspacing}{disabling experimental handler}%
+ \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_old
+ \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_old
+ \enforced\let\directvspacing\directvspacing_old
+ \enforced\let\directvpenalty\directvpenalty_old
+ \enforced\let\directvskip\directvskip_old
+ \enforced\let\inhibitblank\inhibitblank_old}
\protect \endinput
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index d3e36d330..4970622c9 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 e449f1238..ceb04ac24 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/strc-con.mklx b/tex/context/base/mkiv/strc-con.mklx
new file mode 100644
index 000000000..ce7f60176
--- /dev/null
+++ b/tex/context/base/mkiv/strc-con.mklx
@@ -0,0 +1,1156 @@
+%D \module
+%D [ file=strc-con,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Constructions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Constructions}
+
+\registerctxluafile{strc-con}{}
+
+% todo: check why \copy .. probably mkii leftover
+%
+% todo: check if commands similar to lists
+% todo: \strc_constructions_setup_counter\strc_constructions_setup_counter{#1} in setup ... synchronization
+%
+% ? : \def\showdnlisttext{\constructionparameter\c!listtext} % space in default
+%
+% maybe: pickup text and store in buffer ...
+%
+% \@@notemakeconstruction[##1]{}{##2}%
+% \expandafter\endgroup\noteparameter\c!next}}
+%
+% todo: \currentconstructionattribute : can be a counter instead
+
+%D Constructions are just descriptions but a bit more abstract so that we can
+%D conveniently build upon them. They are not really meant for users but module
+%D writers might find them useful. We mention a couple of parameters but these are
+%D only mentioned because in the shared code we map all resolvers to constructions.
+%D
+%D On top of constructions we build descriptions, enumerations, notes, labels and
+%D maybe some day more.
+
+\unprotect
+
+%D Todo:
+
+\installcorenamespace{construction}
+
+\installcommandhandler \??construction {construction} \??construction
+
+\aliased\let\setupconstructions\setupconstruction
+
+\setupconstructions[%
+ %c!title=,
+ %c!text=,
+ %
+ %c!style=,
+ %c!color=,
+ %c!command=,
+ %c!align=,
+ %
+ %c!headstyle=,
+ %c!headcolor=,
+ %c!headalign=,
+ %
+ %c!titlestyle=,
+ %c!titlecolor=,
+ %c!titlecommand=,
+ %c!titleleft=,
+ %c!titleright=,
+ %
+ %c!closesymbol=,
+ %c!closecommand=,
+ %
+ \c!alternative=\v!left,
+ \c!display=\v!yes,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!stretch=.50,
+ \c!shrink=.25,
+ \c!titledistance=.5\emwidth,
+ %c!hang=,
+ %c!sample=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %c!indentnext=,
+ %c!indenting=,
+ %
+ \c!expansion=\v!no,
+ %c!xmlsetup=,
+ %s!catcodes=,
+]
+
+%D Constructions and alike uses similar structures. In order to prevent issues
+%D we freeze some states. There is some overhead in the intermediate define
+%D step (as we could set them directly) but this is more flexible (and looks
+%D nicer). Keep in mind that descriptions, enumeration and notations are all
+%D independent and that we just remap the resolvers.
+
+% \defineconstruction[test][handler=description,level=1]
+% \defineconstruction[test][parent][handler=description,level=3]
+
+\installcorenamespace{constructionmain} % frozen after definition
+\installcorenamespace{constructionlevel} % frozen after definition
+\installcorenamespace{constructionclass} % frozen after definition
+
+\let\currentconstructionmain \empty
+\let\currentconstructionlevel \empty
+\let\currentconstructionhandler\empty
+
+\settrue\c_strc_constructions_define_commands % use with care, might become a proper key
+
+\appendtoks
+ \ifx\currentconstructionparent\empty
+ \letvalue{\??constructionmain\currentconstruction}\currentconstruction
+ \definelist[\currentconstruction]% goodie
+ \else
+ \letvalue{\??constructionmain\currentconstruction}\currentconstructionparent
+ \definelist[\currentconstruction][\currentconstructionparent]% goodie
+ \fi
+ \instance\setevalue{\??constructionlevel\currentconstruction}{\number\constructionparameter\c!level}%
+ \instance\setevalue{\??constructionclass\currentconstruction}{\constructionparameter\s!handler}%
+\to \everydefineconstruction
+
+\appendtoks
+ \ifconditional\c_strc_constructions_define_commands
+ %% \setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}%
+ \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start[\currentconstruction]}%
+ \instance\setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}%
+ \fi
+\to \everydefineconstruction
+
+%D Just a basic environment (mostly for testing). We will provide a 'setup' based
+%D plugin once the rest is sorted out.
+
+\tolerant\protected\def\strc_constructions_start[#1]#*[#2]#*[#3]%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \strc_constructions_register[#3][\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#2]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\protected\def\strc_constructions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname
+ \endgroup}
+
+%D As we will build on top of the generic construction mechanism we have handlers
+%D as a sort of plug in mechanism. In order to have some consistency we share
+%D some namespaces.
+
+\installcorenamespace{constructioninitializer}
+\installcorenamespace{constructionfinalizer}
+
+\installcorenamespace{constructionmainhandler}
+\installcorenamespace{constructioncommandhandler}
+\installcorenamespace{constructionstarthandler}
+\installcorenamespace{constructionstophandler}
+
+\installcorenamespace{constructiontexthandler}
+\installcorenamespace{constructionnotehandler}
+
+\protected\def\strc_constructions_initialize#1% class instance
+ {\edef\currentconstruction{#1}%
+ \enforced\let\currentconstructionhash\??construction
+ \let\currentconstructionlistentry\!!zerocount
+ \enforced\expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname
+ \enforced\expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname
+ \enforced\expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname
+ \csname\??constructioninitializer\currentconstructionhandler\endcsname}
+
+\protected\def\strc_constructions_finalize
+ {\csname\??constructionfinalizer\currentconstructionhandler\endcsname
+ \strc_constructions_discard}
+
+\newconditional\c_strc_constructions_number_state
+\newconditional\c_strc_constructions_title_state
+
+\protected\setvalue{\??constructioninitializer\v!construction}%
+ {\setfalse\c_strc_constructions_number_state
+ \setfalse\c_strc_constructions_title_state}
+
+\protected\setvalue{\??constructionfinalizer\v!construction}%
+ {}
+
+%D We keep the command variant around but rather would move to the start-stop one.
+%D Also, passing the title as argument has some history so we need to keep that as
+%D well.
+
+% \ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi
+
+% \startuseMPgraphic{MyFrame}
+% picture p ; numeric o ; path a, b ; pair c ;
+% p := textext.rt("\FunnyFramed{\currentconstructiontext}") ;
+% % p := textext.rt("\wrappedconstruction{\FunnyFramed{\currentconstructiontext}}") ;
+% % p := textext.rt("\FunnyFramed{\wrappedconstruction{\currentconstructiontext}}") ;
+% % p := textext.rt("\FunnyFramed{\wrappedcurrentconstruction}") ;
+% ...
+% \stopuseMPgraphic
+%
+% \defineoverlay[MyFrame][\useMPgraphic{MyFrame}]
+%
+% \defineframedtext
+% [MyText]
+% [frame=off,
+% background=MyFrame]
+%
+% \defineenumeration[Theorem]
+% [alternative=empty,
+% before=\startMyText,
+% after=\stopMyText]
+
+\newtoks\everyconstruction
+
+\permanent\protected\def\currentconstructiontext
+ {\begstrut
+ \csname\??constructiontexthandler\currentconstructionhandler\endcsname
+ \endstrut}
+
+\permanent\protected\def\currentconstructionsample
+ {\begstrut
+ \constructionparameter\c!text
+ \p_strc_constructions_sample
+ \endstrut}
+
+\permanent\protected\def\wrappedconstruction#1%
+ {\begingroup
+ \iftrialtypesetting \else
+ \currentconstructionsynchronize
+ \c_attr_destination\currentconstructionattribute\relax
+ \fi
+ #1%
+ \endgroup}
+
+\permanent\protected\def\wrappedcurrentconstruction
+ {\begingroup
+ \iftrialtypesetting \else
+ \currentconstructionsynchronize
+ \c_attr_destination\currentconstructionattribute\relax
+ \fi
+ \currentconstructiontext
+ \endgroup}
+
+\protected\setvalue{\??constructionmainhandler\v!construction}#1%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize % reinstated
+ \c_attr_destination\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#1}
+
+\protected\setvalue{\??constructiontexthandler\v!construction}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext
+ \the\everyconstruction
+ \constructionparameter\c!headcommand
+ {\strut
+ \constructionparameter\c!text
+ \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}%
+ \endgroup}
+
+\protected\def\strc_constructions_stored_start
+ {\begingroup % brrr \endgroup elsewhere ... will be sorted out
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\protected\def\strc_constructions_stored_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname}
+
+\newconstant\c_strc_constructions_nested_state % to be redone
+
+\def\resetconstructions % to be used in e.g. footnotes
+ {\c_strc_constructions_nested_state\zerocount}
+
+\protected\setvalue{\??constructioncommandhandler\v!construction}%
+ {\endgroup}
+
+\let\p_strc_constructions_sample \empty
+\let\p_strc_constructions_align \empty
+\let\p_strc_constructions_indenting \empty
+\let\p_strc_constructions_width \empty
+\let\p_strc_constructions_aligntitle \empty
+\let\p_strc_constructions_renderingsetup\empty
+\let\p_strc_constructions_headalign \empty
+\let\p_strc_constructions_hang \empty
+\let\p_strc_constructions_inbetween \empty
+\let\p_strc_constructions_closesymbol \empty
+\let\p_strc_constructions_distance \empty
+
+\newconditional\c_strc_constructions_distance_none
+
+\def\strc_constructions_set_width_and_distance
+ {\assignwidth
+ \p_strc_constructions_width
+ \constructionsheadwidth
+ {\unhcopy\constructionheadbox}
+ \constructionsheaddistance}
+
+\def\strc_constructions_preroll_head#content%
+ {\setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \settrialtypesetting
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname#content}}
+
+\def\strc_constructions_ignore_head
+ {\constructionsheaddistance\zeropoint
+ \constructionsheadwidth \zeropoint
+ % 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
+ \constructionparameter\c!before
+ \begingroup
+ \edef\currentconstructionalternative{\constructionparameter\c!alternative}%
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}%
+ % catch fuzzyness
+ \ifx\p_strc_constructions_renderingsetup\empty
+ \letconstructionparameter\c!alternative\v!left
+ \let\currentconstructionalternative\v!left
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}%
+ \else
+ \doifnotsetups\p_strc_constructions_renderingsetup
+ {\letconstructionparameter\c!alternative\v!left
+ \let\currentconstructionalternative\v!left
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}}%
+ \fi
+ %
+ \doadaptleftskip{\constructionparameter\c!margin}%
+ \setlocalhsize % so we can use \localhsize in width assignments
+ \edef\p_strc_constructions_distance{\constructionalternativeparameter\c!distance}%
+ \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}%
+ \ifx\p_strc_constructions_distance\v!none
+ \settrue\c_strc_constructions_distance_none
+ \constructionsheaddistance\zeropoint
+ \else
+ \setfalse\c_strc_constructions_distance_none
+ \constructionsheaddistance\p_strc_constructions_distance\relax
+ \ifdim\constructionsheaddistance=\zeropoint
+ \ifx\p_strc_constructions_width\v!broad
+ \constructionsheaddistance\emwidth
+ \orelse\ifx\p_strc_constructions_width\v!line
+ \constructionsheaddistance\emwidth
+ \fi
+ \fi
+ \fi
+ % inefficient and not always needed, for instance not with margins so we will make checkers
+ % per alternative some day (especially in labels this is unwanted overhead)
+ %
+ % maybe we should have an option as i cannot oversee the consequences now
+ %
+ % \edef\p_strc_constructions_sample{\constructionparameter\c!sample}%
+ % \ifx\p_strc_constructions_sample\empty
+ % \strc_constructions_preroll_head\currentconstructiontext
+ % \else
+ % \strc_constructions_preroll_head\currentconstructiontextsample
+ % \fi
+ % \strc_constructions_set_width_and_distance
+ %
+ \strc_constructions_preroll_head\currentconstructiontext
+ \ifzeropt\wd\constructionheadbox
+ \strc_constructions_ignore_head
+ \else
+ \edef\p_strc_constructions_sample{\constructionparameter\c!sample}%
+ \ifx\p_strc_constructions_sample\empty
+ \strc_constructions_set_width_and_distance
+ \else
+ \strc_constructions_preroll_head\currentconstructionsample
+ \ifzeropt\wd\constructionheadbox
+ \strc_constructions_ignore_head
+ \else
+ \strc_constructions_set_width_and_distance
+ \fi
+ \fi
+ \fi
+ %
+ \dostarttagged\t!constructiontag\empty % todo
+ \setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \ifx\currentconstructionalternative\v!serried % brrr, hack, will change
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext
+ \else
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}%
+ \fi}%
+ \edef\p_strc_constructions_aligntitle{\constructionparameter\c!aligntitle}%
+ \ifx\p_strc_constructions_aligntitle\v!no
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \else
+ \ifcase\c_strc_constructions_nested_state
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \fi
+ \fi
+ \edef\p_strc_constructions_align{\constructionparameter\c!align}%
+ \ifx\p_strc_constructions_align\empty \else
+ \setupalign[\p_strc_constructions_align]% \use...
+ \fi
+ \ifcase\c_strc_constructions_nested_state
+ \c_strc_constructions_nested_state\plusone
+ \or
+ \c_strc_constructions_nested_state\plustwo
+ \fi
+ \strc_constructions_close_symbol_reset
+ %
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ %
+ \directsetup\p_strc_constructions_renderingsetup\relax
+ % moved to here 2014-07-03
+ \edef\p_strc_constructions_indenting{\constructionparameter\c!indenting}%
+ \ifx\p_strc_constructions_indenting\empty \else
+ \indenting[\p_strc_constructions_indenting]% \use...
+ \fi
+ %
+ \dostoptagged % tag
+ \dostarttagged\t!constructioncontent\empty
+ %\freezeparagraphproperties
+ \updateparagraphshapes
+ \ignorespaces} % args not needed
+
+\protected\setvalue{\??constructionstophandler\v!construction}%
+ {\strc_constructions_close_symbol_place
+ \doifnot{\constructionparameter\c!display}\v!no\par
+ \dostoptagged % content
+ \dostoptagged % construction
+ \endgroup
+ \constructionparameter\c!after
+ \useindentnextparameter\constructionparameter
+ \strc_constructions_finalize
+% \endgroup
+ \dorechecknextindentation}
+
+\protected\def\boxedconstructionhead#1%
+ {\doifelse{\constructionalternativeparameter\c!alignbottom}{\v!yes}\vbox\vtop
+ {\hsize\constructionsheadwidth
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ \ifx\p_strc_constructions_headalign\empty \else
+ \setupalign[\p_strc_constructions_headalign]% \use...
+ \fi
+ #1}}
+
+\installcorenamespace{constructionalternative}
+\installcorenamespace{constructionrenderings}
+
+% see lists: alternativemethods ... todo
+%
+% there will be a proper interface to variables
+
+\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative
+
+\setupconstructionalternative
+ [%c!left=, % no inheritance
+ %c!right=,% no inheritance
+ \c!width=\constructionparameter\c!width,
+ \c!distance=\constructionparameter\c!distance,
+ \c!stretch=\constructionparameter\c!stretch,
+ \c!shrink=\constructionparameter\c!shrink]
+
+\defineconstructionalternative
+ [\v!left]
+ [%\c!width=7em,
+ %\c!distance=1em,
+ \c!renderingsetup=\??constructionrenderings:\v!left]
+
+\defineconstructionalternative
+ [\v!right]
+ [%\c!width=7em,
+ %\c!distance=1em,
+ \c!renderingsetup=\??constructionrenderings:\v!right]
+
+\defineconstructionalternative
+ [\v!inmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!inmargin]
+
+\defineconstructionalternative
+ [\v!inleft]
+ [\c!renderingsetup=\??constructionrenderings:\v!inleft]
+
+\defineconstructionalternative
+ [\v!inright]
+ [\c!renderingsetup=\??constructionrenderings:\v!inright]
+
+\defineconstructionalternative
+ [\v!margin]
+ [\c!renderingsetup=\??constructionrenderings:\v!margin]
+
+\defineconstructionalternative
+ [\v!leftmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!leftmargin]
+
+\defineconstructionalternative
+ [\v!rightmargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!rightmargin]
+
+\defineconstructionalternative
+ [\v!innermargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!innermargin]
+
+\defineconstructionalternative
+ [\v!outermargin]
+ [\c!renderingsetup=\??constructionrenderings:\v!outermargin]
+
+\defineconstructionalternative
+ [\v!serried]
+ [\c!renderingsetup=\??constructionrenderings:\v!serried]
+
+\defineconstructionalternative
+ [\v!hanging]
+ [%\c!width=.75\emwidth
+ \c!renderingsetup=\??constructionrenderings:\v!hanging]
+
+\defineconstructionalternative
+ [\v!top]
+ [\c!renderingsetup=\??constructionrenderings:\v!top,
+ \c!width=\localhsize]
+
+\defineconstructionalternative
+ [\v!command]
+ [\c!renderingsetup=\??constructionrenderings:\v!command]
+
+\defineconstructionalternative
+ [\v!empty]
+ [\c!renderingsetup=\??constructionrenderings:\v!empty]
+
+\defineconstructionalternative
+ [\v!label]
+ [\c!renderingsetup=\??constructionrenderings:\v!label,
+ \c!width=]
+
+\newbox \constructionheadbox
+\newskip \leftconstructionskip
+\newskip \rightconstructionskip
+\newdimen \constructionsheadwidth % replaces \!!widtha % TODO: proper namespace dimens
+\newdimen \constructionsheaddistance % replaces \!!widthb % TODO: proper namespace dimens
+
+\def\strc_constructions_set_hang_box#1% messy left/rightskip
+ {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang
+ {\forgetall
+ \dontcomplain
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_strc_constructions_headalign]% use fast one
+ \fi
+ \ifconditional\c_strc_constructions_distance_none \else
+ \advance\ifx#1\v!flushleft\rightskip\else\leftskip\fi\constructionsheaddistance % only difference and wrong anyway
+ \fi
+ \flushconstructionheadbox}%
+ \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
+ \ht\constructionheadbox\strutht
+ \dp\constructionheadbox\strutdp}
+
+\def\strc_constructions_set_pure_box#1% default ... better set up differently
+ {\setbox\constructionheadbox\vtop
+ {\forgetall
+ \dontcomplain
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_strc_constructions_headalign]% use fast one
+ \fi
+ \flushconstructionheadbox}%
+ \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
+ \ht\constructionheadbox\strutht
+ \dp\constructionheadbox\strutdp}
+
+\def\strc_constructions_set_hang#1%
+ {\ifx\p_strc_constructions_hang\empty
+ % nothing
+ \orelse\ifx\p_strc_constructions_hang\v!fit
+ \scratchdimen\htdp\constructionheadbox
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \orelse\ifx\p_strc_constructions_hang\v!broad
+ \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \else
+ \hangafter-\p_strc_constructions_hang
+ \fi
+ \relax
+ \hangindent\ifx#1\v!right-\fi\constructionsheadwidth}
+
+\protected\def\flushconstructionheadbox
+ {\ifhbox\constructionheadbox\unhbox\else\box\fi\constructionheadbox}
+
+% The setups. These only deal with placement of the descriptor and initializing the
+% environment. The wrapping happens elsewhere.
+
+% todo: optimize the setups with
+%
+% \ifconditional\c_strc_constructions_distance_none : no need for skip
+% \ifzeropt\wd\constructionheadbox : no need for box and skips
+
+\startsetups[\??constructionrenderings:\v!left]
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}%
+ \doifelsesetups{\??constructionrenderings:\v!left:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!left:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right]
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}
+ \doifelsesetups{\??constructionrenderings:\v!right:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!right:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!none]
+ \enforced\let\\\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
+ \rightskip\rightconstructionskip\relax
+ \llap {
+ \hpack to \leftskip {
+ \hskip\leftconstructionskip
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:0]
+ \directsetup{\??constructionrenderings:\v!left:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:]
+ \directsetup{\??constructionrenderings:\v!left:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!none]
+ \enforced\let\\\crlf
+ \noindent
+ \leftskip\leftconstructionskip
+ \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax
+ %\strc_constructions_pure_hang_box\raggedleft
+ \strc_constructions_set_pure_box\v!flushright
+ \rlap {
+ \hskip\dimexpr\hsize-\leftskip-\rightskip\relax
+ \copy\constructionheadbox
+ \hskip\rightconstructionskip
+ }
+ \nobreak
+ \advance\rightskip \constructionsheaddistance
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:0]
+ \directsetup{\??constructionrenderings:\v!right:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:]
+ \directsetup{\??constructionrenderings:\v!right:\v!none}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!margin]%
+ \enforced\let\\\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \llap {
+ \hpack to \constructionsheadwidth {
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ \hskip\constructionsheaddistance
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!margin]%
+ \enforced\let\\\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushright
+ \rlap {
+ \hskip\constructionsheaddistance
+ \hpack to \constructionsheadwidth {
+ \box\constructionheadbox % was copy
+ \hss
+ }
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!hanging]%
+ \enforced\let\\\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushleft
+ \strc_constructions_set_hang\v!left
+ \noindent
+ \llap {
+ \tpack to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!hanging]%
+ \enforced\let\\\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushright
+ \strc_constructions_set_hang\v!right
+ \noindent
+ \rlap {
+ \hpack to \dimexpr\hsize-\leftskip-\rightskip\relax {
+ \hss
+ \tpack to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ }
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!top]
+ % \strc_sectioning_prevent_page_break % commented per 31/5/2019
+ \enforced\let\\\space
+ \noindent
+ \copy\constructionheadbox % why copy ?
+ \par
+ \nobreak
+ \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}%
+ \ifx\p_strc_constructions_inbetween\empty \else
+ \p_strc_constructions_inbetween
+ % shouldn't this move to after the fi?
+ \directcheckedvspacing\v!samepage
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+% why copy? historic reason?
+
+\startsetups[\??constructionrenderings:\v!margin]
+ \enforced\let\\\crlf
+ \noindent
+ \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!leftmargin]
+ \enforced\let\\\crlf
+ \noindent
+ \inleft[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!rightmargin]
+ \enforced\let\\\crlf
+ \noindent
+ \inright[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!innermargin]
+ \enforced\let\\\crlf
+ \noindent
+ \ininner[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!outermargin]
+ \enforced\let\\\crlf
+ \noindent
+ \inouter[\c!scope=\v!local]{\flushconstructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inmargin]
+ \directsetup{\??constructionrenderings:\v!margin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inleft]
+ \directsetup{\??constructionrenderings:\v!leftmargin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!inright]
+ \directsetup{\??constructionrenderings:\v!rightmargin}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried]
+ % already set?
+ \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace
+ \doifelsesetups{\??constructionrenderings:\v!serried:\p_strc_constructions_width} {
+ \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width}
+ } {
+ \directsetup{\??constructionrenderings:\v!serried:\v!wide}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!fit]
+ \enforced\let\\\crlf
+ \noindent
+ \flushconstructionheadbox
+ \nobreak
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!broad]
+ \enforced\let\\\crlf
+ \noindent
+ \flushconstructionheadbox
+ \ifconditional\c_strc_constructions_distance_none \else
+ \nobreak
+ \hskip\constructionsheaddistance
+ \s!plus \constructionalternativeparameter\c!stretch\constructionsheaddistance
+ \s!minus\constructionalternativeparameter\c!shrink \constructionsheaddistance
+ \relax
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:]
+ \directsetup{\??constructionrenderings:\v!serried:\v!broad}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!wide]
+ \enforced\let\\\crlf
+ \noindent
+ \hbox to \constructionsheadwidth {
+ \flushconstructionheadbox
+ \hss
+ }
+ \nobreak
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!hanging]
+ % tricky: leftskipadaption is somewhat unpredictable
+ \enforced\let\\\crlf
+ \noindent
+ \advance\leftskip-\leftskipadaption\relax
+ \ifdim\leftskipadaption=\zeropoint
+ \leftskipadaption1.5\emwidth\relax % just some default
+ \ifnum\c_strc_constructions_nested_state=\plusone
+ \ifdim\leftskip>\zeropoint \relax
+ \leftskipadaption\leftskip
+ \fi
+ \fi
+ \fi
+ \ifnum\c_strc_constructions_nested_state>\zerocount % was \ifnum\c_strc_constructions_nested_state=\plusone
+ \advance\leftskip\leftskipadaption % but we're already further on
+ \fi
+ \hskip-\leftskipadaption\relax
+ \ifhbox\constructionheadbox \unhbox\else\box\fi\constructionheadbox
+ \ifconditional\c_strc_constructions_distance_none \else
+ % we used to have just a kern, but long lines look bad then
+ \scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi
+ \hskip \scratchdistance
+ \s!plus \constructionalternativeparameter\c!stretch\scratchdistance
+ \s!minus\constructionalternativeparameter\c!shrink \scratchdistance
+ \fi
+ \ifhmode
+ \ifx\p_strc_constructions_width\v!line
+ \hfill\break
+ \else
+ \allowbreak
+ \fi
+ \fi
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+%D \starttyping
+%D \setupfootnotation[location=command,headcommand=\llap]
+%D \stoptyping
+
+\startsetups[\??constructionrenderings:\v!command]
+ \noindent
+ \constructionparameter\c!headcommand{\flushconstructionheadbox}
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!empty]
+ \noindent
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!label]
+ \dontleavehmode
+ \begingroup
+ \constructionparameter\c!headcommand{\flushconstructionheadbox}
+ \endgroup
+\stopsetups
+
+\ifcase\contextlmtxmode \else
+ % just an empty check so that we can grep for contextlmtxmode in mkiv files
+\fi
+
+% \definedescription[whatever][alternative=right:bottom]
+%
+% \startwhatever{just a small\\example}
+% \input ward
+% \stopwhatever
+
+\defineconstructionalternative
+ [\v!right:\v!bottom]
+ [%\c!width=7em,
+ %\c!distance=1em,
+ \c!alignbottom=\v!yes,
+ \c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom]
+
+\startsetups[\??constructionrenderings:\v!right:\v!bottom]
+ \enforced\let\\\crlf
+ \noindent
+ \leftskip\leftconstructionskip
+ \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
+ \parfillskip\zeropoint
+ \strc_constructions_set_pure_box\v!flushright
+ \directparwrapper \relax {%
+ \hfilll
+ \rlap
+ {\kern\constructionsheaddistance
+ \copy\constructionheadbox}%
+ }%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+%D This next feature will get an lmtx implementation (probably by using a new generic
+%D close mechanism).
+
+% you can use \placeclosesymbol or \qed to place a symbol at the end of a
+% construction
+
+\installcorenamespace{constructionclosesymbol}
+
+\let\placeclosesymbol\donothing
+\let\qed \donothing
+
+\def\strc_constructions_close_symbol_reset % no need for global
+ {\global\expandafter\settrue\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \let\placeclosesymbol\strc_constructions_close_symbol_place
+ \let\qed \strc_constructions_close_symbol_place}
+
+\protected\def\strc_constructions_close_symbol_place
+ {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}%
+ \ifx\p_strc_constructions_closesymbol\empty \else
+ \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected
+ \fi
+ \fi}
+
+\newif\ifnoconstructioncaption
+
+%D The storage macros:
+
+\let\currentconstructionlistentry\!!zerocount
+
+\protected\def\strc_constructions_register
+ {\clf_doifelselisthasentry\numexpr\currentconstructionlistentry\relax
+ \strc_constructions_register_nop
+ \strc_constructions_register_yes}
+
+% \def\strc_constructions_register{\strc_constructions_register_yes}
+
+\def\strc_constructions_register_nop[#1][#2]% #1=optional user data #2=interfaced-settings
+ %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}}
+ {}
+
+\def\strc_constructions_discard
+ {\iftrialtypesetting
+ % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}%
+ \clf_discardfromlist\currentconstructionlistentry\relax
+ \fi}
+
+\let\currentconstructionlistnumber \!!zerocount
+\let\currentconstructionsynchronize\relax
+\let\currentconstructionattribute \attributeunsetvalue
+
+\def\strc_constructions_register_yes[#1][#2]% #1=optional user data #2=interfaced-settings
+ {\begingroup % similar to structure so we might generalize this
+ \setupcurrentconstruction[#2]% % xdef's will become edef's
+ \xdef\currentconstructionexpansion {\constructionparameter\c!expansion}%
+ \xdef\currentconstructionxmlsetup {\constructionparameter\c!xmlsetup}%
+ \xdef\currentconstructioncatcodes {\constructionparameter\s!catcodes}%
+ \xdef\currentconstructionlabel {\constructionparameter\c!label}%
+ \xdef\currentconstructionreference {\constructionparameter\c!reference}%
+ \xdef\currentconstructionreferenceprefix{\constructionparameter\c!referenceprefix}%
+ %xdef\currentconstructionshownumber {\constructionparameter\c!number}%
+ \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}%
+ %
+ \ifx\currentconstructionexpansion\empty
+ \glet\currentconstructionexpansion\v!no
+ \fi
+ %
+ \ifx\currentconstructionreferenceprefix\empty
+ \glet\currentconstructionreferenceprefix\referenceprefix
+ \fi
+ \ifx\currentconstructionexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentconstructiontitle {\constructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\constructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\constructionparameter\c!list}%
+ \xmlstopraw
+ \ifx\currentconstructionlist\empty
+ \glet\currentconstructionlist\currentconstructiontitle
+ \fi
+ \glet\currentconstructioncoding\s!xml
+ \else
+ \ifx\currentconstructionexpansion\v!yes
+ \xdef\currentconstructiontitle {\constructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\constructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\constructionparameter\c!list}%
+ \else
+ \xdef\currentconstructiontitle {\detokenizedconstructionparameter\c!title}%
+ \xdef\currentconstructionbookmark{\detokenizedconstructionparameter\c!bookmark}%
+ \xdef\currentconstructionmarking {\detokenizedconstructionparameter\c!marking}%
+ \xdef\currentconstructionlist {\detokenizedconstructionparameter\c!list}%
+ \iflocation \ifx\currentconstructionbookmark\empty
+ \begingroup
+ \simplifycommands
+ \xdef\currentconstructionbookmark{\detokenize\expandafter{\normalexpanded{\constructionparameter\c!title}}}%
+ \endgroup
+ \fi \fi
+ \fi
+ \ifx\currentconstructionlist\empty
+ \glet\currentconstructionlist\currentconstructiontitle
+ \fi
+ \glet\currentconstructioncoding\s!tex
+ \fi
+ %
+ \ifx\currentconstructiontitle\v!none % will become obsolete
+ \global\noconstructioncaptiontrue\global\noconstructionnumbertrue
+ \fi
+ %
+ \ifnoconstructioncaption % then why analyze anyway?
+ \endgroup
+ \let\currentconstructionlistnumber \relax
+ \let\currentconstructionsynchronize\relax
+ \let\currentconstructionattribute \relax
+ \else
+ \setnextinternalreferences{construction}\currentconstructionmain % plural
+ \relax
+ \scratchcounter\clf_addtolist
+ metadata {
+ kind {construction}
+ name {\currentconstructionmain}
+ % level structures.sections.currentlevel()
+ catcodes \catcodetable
+ }
+ references {
+ internal \locationcount
+ order \locationorder
+ reference {\currentconstructionreference}
+ prefix {\currentconstructionreferenceprefix}
+ % block {\currentsectionblock}
+ % section structures.sections.currentid(),
+ }
+ titledata {
+ label {\detokenize\expandafter{\currentconstructionlabel}}
+ title {\detokenize\expandafter{\currentconstructiontitle}}
+ \ifx\currentconstructionbookmark\currentconstructiontitle \else
+ bookmark {\detokenize\expandafter{\currentconstructionbookmark}}
+ \fi
+ \ifx\currentconstructionlist\currentconstructiontitle \else
+ list {\detokenize\expandafter{\currentconstructionlist}}
+ \fi
+ }
+ \ifconditional\c_strc_constructions_number_state
+ prefixdata {
+ prefix {\constructionparameter\c!prefix}
+ separatorset {\constructionparameter\c!prefixseparatorset}
+ conversion {\constructionparameter\c!prefixconversion}
+ conversionset {\constructionparameter\c!prefixconversionset}
+ set {\constructionparameter\c!prefixset}
+ segments {\constructionparameter\c!prefixsegments}
+ connector {\constructionparameter\c!prefixconnector}
+ }
+ numberdata {
+ numbers {\currentconstructionnumber}
+ separatorset {\constructionparameter\c!numberseparatorset}
+ conversion {\constructionparameter\c!numberconversion}
+ conversionset {\constructionparameter\c!numberconversionset}
+ starter {\constructionparameter\c!numberstarter}
+ stopper {\constructionparameter\c!numberstopper}
+ segments {\constructionparameter\c!numbersegments}
+ }
+ \or
+ % symbol
+ \fi
+ userdata {\detokenize{#1}}
+ \relax
+ % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}%
+ \clf_setinternalreference
+ prefix {\currentconstructionreferenceprefix}%
+ reference {\currentconstructionreference}%
+ internal \locationcount
+ view {\interactionparameter\c!focus}%
+ \relax
+ \normalexpanded {%
+ \endgroup
+ \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}%
+ \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}%
+ \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}%
+ }%
+ \fi}
+
+% This is not so nice, some day I'll just store the number with the entry
+% and deal with all at the Lua end, but first we need to be able to set
+% macros.
+
+\permanent\protected\def\reinstateconstructionnumberentry#1% was xdef
+ {\edef\currentconstructionattribute {\clf_getinternallistreference#1}%
+ \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}}
+
+\permanent\protected\def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real
+ {\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination
+ \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}}
+
+\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}}
+
+% Helpers:
+
+\def\currentconstructionnumber{\constructionparameter\s!counter}
+
+\protected\def\strc_constructions_next_indeed #get#tag#level{\strc_counters_increment_sub{#get{#tag}\s!counter}{#level}}
+\protected\def\strc_constructions_reset_indeed#get#tag#level{\strc_counters_reset_sub {#get{#tag}\s!counter}{#level}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi
index 681e813b7..81e28f67f 100644
--- a/tex/context/base/mkiv/strc-con.mkvi
+++ b/tex/context/base/mkiv/strc-con.mkvi
@@ -620,7 +620,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!left:\v!none]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\strc_constructions_set_pure_box\v!flushleft
\leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
@@ -646,7 +646,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!right:\v!none]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\leftskip\leftconstructionskip
\rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax
@@ -672,7 +672,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!left:\v!margin]%
- \let\\=\crlf
+ \let\\\crlf
\noindent
\strc_constructions_set_pure_box\v!flushleft
\llap {
@@ -687,7 +687,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!right:\v!margin]%
- \let\\=\crlf
+ \let\\\crlf
\noindent
\strc_constructions_set_pure_box\v!flushright
\rlap {
@@ -702,7 +702,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!left:\v!hanging]%
- \let\\=\crlf
+ \let\\\crlf
\dontcomplain
\advance\constructionsheadwidth \constructionsheaddistance
\strc_constructions_set_hang_box\v!flushleft
@@ -719,7 +719,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!right:\v!hanging]%
- \let\\=\crlf
+ \let\\\crlf
\dontcomplain
\advance\constructionsheadwidth \constructionsheaddistance
\strc_constructions_set_hang_box\v!flushright
@@ -740,7 +740,7 @@
\startsetups[\??constructionrenderings:\v!top]
% \strc_sectioning_prevent_page_break % commented per 31/5/2019
- \let\\=\space
+ \let\\\space
\noindent
\copy\constructionheadbox % why copy ?
\par
@@ -758,7 +758,7 @@
% why copy? historic reason?
\startsetups[\??constructionrenderings:\v!margin]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\inmargin[\c!scope=\v!local]{\flushconstructionheadbox}%
\useconstructionstyleandcolor\c!style\c!color
@@ -766,7 +766,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!leftmargin]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\inleft[\c!scope=\v!local]{\flushconstructionheadbox}%
\useconstructionstyleandcolor\c!style\c!color
@@ -774,7 +774,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!rightmargin]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\inright[\c!scope=\v!local]{\flushconstructionheadbox}%
\useconstructionstyleandcolor\c!style\c!color
@@ -782,7 +782,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!innermargin]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\ininner[\c!scope=\v!local]{\flushconstructionheadbox}%
\useconstructionstyleandcolor\c!style\c!color
@@ -790,7 +790,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!outermargin]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\inouter[\c!scope=\v!local]{\flushconstructionheadbox}%
\useconstructionstyleandcolor\c!style\c!color
@@ -820,7 +820,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!serried:\v!fit]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\flushconstructionheadbox
\nobreak
@@ -830,7 +830,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!serried:\v!broad]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\flushconstructionheadbox
\ifconditional\c_strc_constructions_distance_none \else
@@ -849,7 +849,7 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!serried:\v!wide]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\hbox to \constructionsheadwidth {
\flushconstructionheadbox
@@ -863,7 +863,7 @@
\startsetups[\??constructionrenderings:\v!hanging]
% tricky: leftskipadaption is somewhat unpredictable
- \let\\=\crlf
+ \let\\\crlf
\noindent
\advance\leftskip-\leftskipadaption\relax
\ifdim\leftskipadaption=\zeropoint
@@ -939,7 +939,7 @@
\c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom]
\startsetups[\??constructionrenderings:\v!right:\v!bottom]
- \let\\=\crlf
+ \let\\\crlf
\noindent
\leftskip\leftconstructionskip
\rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
diff --git a/tex/context/base/mkiv/strc-des.mklx b/tex/context/base/mkiv/strc-des.mklx
new file mode 100644
index 000000000..9bdb0e6ea
--- /dev/null
+++ b/tex/context/base/mkiv/strc-des.mklx
@@ -0,0 +1,194 @@
+%D \module
+%D [ file=strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Descriptions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Descriptions}
+
+\unprotect
+
+\installcorenamespace{description}
+
+\installcommandhandler \??description {description} \??description
+
+\aliased\let\setupdescriptions\setupdescription
+
+% \setupdescription % check with old
+% [\c!alternative=\descriptionparameter\c!location,
+% \c!location=\v!left]
+
+\setupdescription % check with old
+ [\c!alternative=\v!left,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ \c!title=\v!yes,
+ %\c!text=,
+ ]
+
+\appendtoks
+ \ifx\currentdescriptionparent\empty
+ \defineconstruction[\currentdescription][\currentdescriptionparent][\s!handler=\v!description,\c!level=1]%
+ \else
+ \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]%
+ \fi
+ % We can combine these but in tracing (or errors) using a different caller is nicer.
+ \instance\setuevalue {\currentdescription}{\strc_descriptions_command[\currentdescription]}%
+ \instance\setuevalue{\e!start\currentdescription}{\strc_descriptions_start [\currentdescription]}%
+ \instance\setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}%
+\to \everydefinedescription
+
+\let\p_strc_constructions_title \empty
+
+\protected\setvalue{\??constructioninitializer\v!description}%
+ {\let \currentdescription \currentconstruction
+ \enforced\let\constructionparameter \descriptionparameter
+ \enforced\let\constructionnamespace \??description
+ \enforced\let\detokenizedconstructionparameter\detokenizeddescriptionparameter
+ \enforced\let\letconstructionparameter \letdescriptionparameter
+ \enforced\let\useconstructionstyleandcolor \usedescriptionstyleandcolor
+ \enforced\let\setupcurrentconstruction \setupcurrentdescription
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+% We keep the command variant around but rather would move to the
+% start-stop one. Also, passing the title as argument has some
+% history so we need to keep that as well.
+
+% \startdescription [reference] text \stopdescription
+% \startdescription [reference]{title} text \stopdescription
+% \startdescription [title=,title=,reference=] text \stopdescription
+
+% A bit over the top, the optional title but mkii has it too.
+
+\tolerant\protected\def\strc_descriptions_start[#1]#*[#2]%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \ifhastok={#2}%
+ \expandafter\strc_descriptions_start_setups
+ \orelse\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_start_title
+ \else
+ \expandafter\strc_descriptions_start_reference
+ \fi[#2]}
+
+\protected\def\strc_descriptions_start_setups[#1]%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\protected\tolerant\def\strc_descriptions_start_title[#1]#*#=%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\protected\def\strc_descriptions_start_reference[#1]%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\protected\def\strc_descriptions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname}
+
+% \description [reference] text \par
+% \description [reference] {title} text \par
+
+\tolerant\protected\def\strc_descriptions_command[#1]#*[#2]#:#*#=%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \ifhastok={#2}%
+ \expandafter\strc_descriptions_command_setups
+ \orelse\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_command_title
+ \else
+ \expandafter\strc_descriptions_command_reference
+ \fi[#2]}
+
+\protected\def\strc_descriptions_command_setups[#1]%
+ {\setfalse\c_strc_constructions_title_state
+ \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\protected\tolerant\def\strc_descriptions_command_title[#1]#:#*#=%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\protected\def\strc_descriptions_command_reference[#1]%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+%D Handlers:
+
+\expandafter\let\csname\??constructionmainhandler \v!description\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!description\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname
+\expandafter\let\csname\??constructiontexthandler \v!description\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname
+
+\protected\setvalue{\??constructioncommandhandler\v!description}%
+ {\dowithpar
+ {\csname\??constructionstarthandler\v!construction\endcsname}%
+ {\csname\??constructionstophandler \v!construction\endcsname\endgroup}}
+
+\protected\setvalue{\??constructionstarthandler\v!description}%
+ {\dogotopar
+ {\csname\??constructionstarthandler\v!construction\endcsname}}
+
+\protected\setvalue{\??constructionstophandler\v!description}%
+ {\csname\??constructionstophandler\v!construction\endcsname
+ \endgroup}
+
+%D For historic reasons we have (from now on undocumented):
+
+\definedescription
+ [tab]
+ [\c!alternative=\v!left,
+ \c!headstyle=\v!normal,
+ \c!headcolor=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!width=\v!broad,
+ \c!sample=\kern4\emwidth, % was \hskip but that no longer is okay
+ \c!before=,
+ \c!after=]
+
+\protected\def\setuptab
+ {\setupdescription[tab]}
+
+%D Maybe we should remove this definition.
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-enu.mklx b/tex/context/base/mkiv/strc-enu.mklx
new file mode 100644
index 000000000..6bc2f39d4
--- /dev/null
+++ b/tex/context/base/mkiv/strc-enu.mklx
@@ -0,0 +1,375 @@
+%D \module
+%D [ file=strc-enu, % moved from strc-des
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Enumerations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Enumerations}
+
+\unprotect
+
+% command -> headcommand
+
+%D Enumerations are just super descriptions. Therefore we implement
+%D them as an extension. After all, the keys don't clash. In order
+%D to be able to differentiate between specific settings we use
+%D some flags. Unfortunately we have some historic differences
+%D in default values. Therefore we push an extra step in the
+%D parent chain (we might do the same for regular descriptions).
+
+%D In order to be more flexible with theorems Aditya Mahajan added
+%D support for titles and endsymbols. At the same time we added more
+%D flexible support for inheriting numbers.
+%D
+%D \startbuffer
+%D \defineenumeration[one]
+%D \defineenumeration[two] [one] % clone one
+%D \defineenumeration[three] [counter=one,style=slanted] % only use counter of one
+%D \defineenumeration[four] [three] % clone three
+%D \defineenumeration[five] [three] [counter=five] % clone three and use own counter
+%D \defineenumeration[six] [three] [counter=four] % clone tree and use counter four (undefined)
+%D
+%D \startone test test 6 \stopone
+%D \starttwo test test 7 \stoptwo
+%D \startthree test test 8 \stopthree
+%D \startfour test test 9 \stopfour
+%D \startfive test test 2 \stopfive
+%D \startsix test test 10 \stopsix
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+%D
+%D \starttyping
+%D \setupenumerations[one] [prefix=yes,prefixsegments=section]
+%D \setupenumerations[two] [prefix=yes,prefixsegments=section]
+%D \setupenumerations[three][prefix=yes,prefixsegments=section]
+%D \setupenumerations[four] [prefix=yes,prefixsegments=chapter:section]
+%D \setupenumerations[five] [prefix=yes,prefixsegments=chapter:section]
+%D \setupenumerations[six] [prefix=yes,prefixsegments=chapter:section]
+%D \stoptyping
+
+% list and titles are experimental
+%
+% \definedescription[test] [location=left,hang=4,headalign={right},distance=1em,list=test]
+% \defineenumeration[lemma][title=yes,right=:,textdistance=1em, location=top, titlestyle=\bs,list=lemma]
+% \defineenumeration[ammel][title=yes,right=:,textdistance=.5em,location=left,titlestyle=\it,width=9em]
+%
+% \placelist[enumeration:lemma]
+% \placelist[description:test][width=0pt]
+%
+% \starttest {something something something} \input zapf \stoptest
+% \startlemma {with a title of a certain length} \input tufte \stoplemma
+% \startammel {with a title} \input zapf \stopammel
+%
+% \defineenumeration[lemma][...]
+% \defineenumeration[titledlemma][lemma][title=yes,right=:,text=lemma,list=lemma]
+
+\installcorenamespace{enumeration}
+
+\installcommandhandler \??enumeration {enumeration} \??enumeration
+
+\installcounterassociation{enumeration}
+
+\let\setupenumerations\setupenumeration
+
+\setupenumeration % check with old
+ [\c!alternative=\v!top,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!width=8\emwidth,
+ %\c!distance=\zeropoint,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ %\c!starter=,
+ %\c!stopper=,
+ \c!text=\currentenumeration,
+ \c!number=\v!yes, % else description
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=4]
+
+% to be considered:
+%
+% \let\??construction\??enumeration
+%
+% with push/pop (also at definition time)
+
+\protected\def\strc_define_commands_enumeration#tag#level#parent%
+ {\doifelsenothing{#parent}
+ {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}%
+ \setevalue{\??enumeration#tag:\s!parent}{\??enumeration}}%
+ {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}%
+ \setevalue{\??enumeration#tag:\s!parent}{\??enumeration#parent}}%
+ \instance\setuevalue{\e!next #tag}{\strc_enumerations_next {#tag}{\number#level}}% obsolete
+ \instance\setuevalue{\c!reset#tag}{\strc_enumerations_reset {#tag}{\number#level}}% obsolete
+ %instance\setuevalue{\c!set #tag}{\strc_enumerations_set {#tag}{\number#level}}% obsolete
+ \instance\setuevalue {#tag}{\strc_enumerations_command[#tag]}% we could pass level here as well (faster)
+ \instance\setuevalue{\e!start#tag}{\strc_enumerations_start [#tag]}% we could pass level here as well (faster)
+ \instance\setuevalue{\e!stop #tag}{\strc_enumerations_stop }}
+
+\appendtoks
+ \ifx\currentenumerationparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentenumerationsub\empty
+ \strc_define_commands_enumeration
+ {\currentenumerationsub\currentenumeration}%
+ \plusone
+ \empty
+ \edef\p_levels{\enumerationparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_enumeration
+ {\v!sub\currentenumerationsub\currentenumeration}%
+ \recurselevel
+ {\currentenumerationsub\currentenumeration}%
+ \edef\currentenumerationsub{\v!sub\currentenumerationsub}}%
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentenumerationsub\empty
+ \edef\p_levels{\enumerationparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_enumeration
+ {\currentenumerationsub\currentenumeration}%
+ \recurselevel
+ {\currentenumerationsub\currentenumerationparent}%
+ \edef\currentenumerationsub{\v!sub\currentenumerationsub}}%
+ \fi
+ \edef\p_counter{\enumerationparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentenumeration
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_enumerations_define_counter\p_counter}%
+ \letenumerationparameter\s!counter\p_counter
+ %\strc_enumerations_setup_counter\currentenumeration
+\to \everydefineenumeration
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\protected\setvalue{\??constructioninitializer\v!enumeration}%
+ {\let \currentenumeration \currentconstruction
+ \enforced\let\constructionparameter \enumerationparameter
+ \enforced\let\constructionnamespace \??enumeration
+ \enforced\let\detokenizedconstructionparameter\detokenizedenumerationparameter
+ \enforced\let\letconstructionparameter \letenumerationparameter
+ \enforced\let\useconstructionstyleandcolor \useenumerationstyleandcolor
+ \enforced\let\setupcurrentconstruction \setupcurrentenumeration
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\protected\setvalue{\??constructionfinalizer\v!enumeration}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Interfaces:
+
+\let\strc_enumerations_command\strc_descriptions_command
+\let\strc_enumerations_start \strc_descriptions_start
+\let\strc_enumerations_stop \strc_descriptions_stop
+
+\protected\def\strc_enumerations_next {\strc_constructions_next_indeed \namedenumerationparameter} % #1#2
+\protected\def\strc_enumerations_reset{\strc_constructions_reset_indeed\namedenumerationparameter} % #1#2
+%unexpanded\def\strc_enumerations_set {\strc_constructions_set_indeed \namedenumerationparameter} % #1#2
+
+%D Counters (maybe we can share this code): (not ok yet, messy with notes)
+
+% Maybe we should move counters to the construction level as more derived mechanisms
+% use it \unknown\ so don't depend on names here!
+
+\def\strc_enumerations_define_counter#tag% todo: move inline
+ {\definecounter[#tag]%
+ \registerenumerationcounter{#tag}}
+
+\appendtoks
+ \synchronizeenumerationcounters
+\to \everysetupenumeration
+
+\appendtoks
+ \synchronizeenumerationcounters
+\to \everydefineenumeration
+
+%D Initializer:
+
+%D The handlers.
+
+\newtoks\everyenumeration
+
+\appendtoks
+ \disablepseudocaps % sorry, uppercase causes troubles
+\to \everyenumeration
+
+\expandafter\let\csname\??constructionmainhandler \v!enumeration\expandafter\endcsname\csname\??constructionmainhandler \v!description\endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!enumeration\expandafter\endcsname\csname\??constructioncommandhandler\v!description\endcsname
+\expandafter\let\csname\??constructionstarthandler \v!enumeration\expandafter\endcsname\csname\??constructionstarthandler \v!description\endcsname
+\expandafter\let\csname\??constructionstophandler \v!enumeration\expandafter\endcsname\csname\??constructionstophandler \v!description\endcsname
+
+\protected\setvalue{\??constructiontexthandler\v!enumeration}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+\protected\def\strc_enumerations_text
+ {\the\everyenumeration % will become obsolete
+ \ifconditional\c_strc_constructions_number_state
+ \ifx\currentconstructionreference\!!plustoken
+ \strc_enumerations_full_number_symbol
+ \else\ifx\currentconstructionreference\!!minustoken
+ \strc_enumerations_full_number_nop
+ \else
+ \strc_enumerations_full_number_coupling
+ \fi\fi
+ \else
+ \strc_enumerations_full_number_nop
+ \fi}
+
+\protected\def\strc_enumerations_inject_text_with_space
+ {\edef\p_text{\constructionparameter\c!text}%
+ \ifx\p_text\empty \else
+ \p_text
+ \removeunwantedspaces
+ \nobreakspace
+ \fi}
+
+\protected\def\strc_enumerations_inject_extra_text
+ {\ifconditional\c_strc_constructions_title_state
+ \clf_doifelselisthastitle{\currentconstructionmain}\numexpr\currentconstructionlistentry\relax
+ \strc_enumerations_inject_extra_text_indeed
+ \donothing
+ \fi}
+
+\protected\def\strc_enumerations_inject_text
+ {\constructionparameter\c!numbercommand
+ {\constructionparameter\c!text}}
+
+% head ( number title )
+
+\protected\def\strc_enumerations_inject_extra_text_indeed
+ {\begingroup
+ \hskip\constructionparameter\c!titledistance % we listen to the headstyle
+ \useconstructionstyleandcolor\c!titlestyle\c!titlecolor
+ \constructionparameter\c!titlecommand
+ {\constructionparameter\c!titleleft
+ \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax
+ \constructionparameter\c!titleright}%
+ \endgroup}
+
+\protected\def\strc_enumerations_inject_symbol % todo check
+ {\constructionparameter\c!left
+ \constructionparameter\c!symbol
+ \constructionparameter\c!right}
+
+\protected\def\strc_enumerations_inject_number
+ {\constructionparameter\c!left
+ \constructionparameter\c!starter
+ \clf_savedlistprefixednumber{\currentconstructionmain}\currentconstructionlistentry\relax
+ \constructionparameter\c!stopper
+ \constructionparameter\c!right}
+
+\protected\def\strc_enumerations_inject_text_and_number
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_number}}
+
+\protected\def\strc_enumerations_inject_text_and_symbol
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_symbol}}
+
+\protected\def\strc_enumerations_full_number_yes
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text_and_number
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\protected\def\strc_enumerations_full_number_nop
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\protected\def\strc_enumerations_full_number_symbol
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text_and_symbol
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+% to be used in for instance:
+%
+% coupling=questions .... coupling=answers
+%
+% we will provide some more control, like skipping etc or reference relates
+
+% to do / to be checked
+
+\protected\def\strc_enumerations_full_number_coupling
+ {\iflocation
+ \strc_enumerations_full_number_yes
+ \else
+ \iftrialtypesetting \else
+ % \doenumerationregistercoupling
+ \fi
+ \strc_enumerations_full_number_yes
+ \edef\p_coupling{\constructionparameter\c!coupling}%
+ \ifx\p_coupling\empty \else
+ \symbolreference[order(construction:\p_coupling:\the\locationorder)]%
+ \fi
+ \fi}
+
+\protected\def\strc_enumerations_skip_number_coupling[#tag]% e.g. for questions with no answer
+ {\clf_setnextreferenceorder{construction}{#tag}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-flt.lua b/tex/context/base/mkiv/strc-flt.lua
index e3a0ea30e..59c67efa1 100644
--- a/tex/context/base/mkiv/strc-flt.lua
+++ b/tex/context/base/mkiv/strc-flt.lua
@@ -31,13 +31,13 @@ function builders.checksidefloat(mode,indented)
return indented
end
-appendaction ("newgraf","system","builders.checksidefloat")
-disableaction("newgraf","builders.checksidefloat")
+appendaction ("paragraph","system","builders.checksidefloat")
+disableaction("paragraph","builders.checksidefloat")
interfaces.implement {
name = "enablesidefloatchecker",
onlyonce = true,
actions = function()
- enableaction("newgraf","builders.checksidefloat")
+ enableaction("paragraph","builders.checksidefloat")
end,
}
diff --git a/tex/context/base/mkiv/strc-flt.mkvi b/tex/context/base/mkiv/strc-flt.mkvi
index 91cc3f666..d9fd359c6 100644
--- a/tex/context/base/mkiv/strc-flt.mkvi
+++ b/tex/context/base/mkiv/strc-flt.mkvi
@@ -211,7 +211,7 @@
\let\strc_floats_define_saved\definefloat
-\unexpanded\def\definefloat
+\unexpanded\overloaded\def\definefloat
{\dotripleempty\strc_floats_define}
\def\strc_floats_define[#1][#2][#3]% name+plural+parent | name+parent+settings
@@ -1230,7 +1230,7 @@
\let\doifoddpagefloatelse \doifelseoddpagefloat
\appendtoks
- \let\rightorleftpageaction\doifelserightpagefloat
+ \overloaded\frozen\let\rightorleftpageaction\doifelserightpagefloat
\to \everyinsidefloat
% \let\movesidefloat\gobbleoneargument
diff --git a/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx
index 86d2275d7..aa105af33 100644
--- a/tex/context/base/mkiv/strc-itm.mklx
+++ b/tex/context/base/mkiv/strc-itm.mklx
@@ -328,7 +328,7 @@
\installcommandhandler \??itemgroup {itemgroup} \??itemgroup
-\let\setupitemgroups\setupitemgroup
+\aliased\let\setupitemgroups\setupitemgroup
\appendtoks
\setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}%
@@ -386,12 +386,12 @@
\vspacing[\v!item @500]%
\fi}
-\unexpanded\def\strc_itemgroups_process_options#options%
+\protected\def\strc_itemgroups_process_options#options%
{\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml
% \installcommalistprocessorcommand \strc_itemgroups_process_option_list \strc_itemgroups_process_option
%
-% \unexpanded\def\strc_itemgroups_process_options#options%
+% \protected\def\strc_itemgroups_process_options#options%
% {\normalexpanded{\strc_itemgroups_process_option_list[#options]}} % expansion of options is handy for xml
\def\strc_itemgroups_process_option#option%
@@ -599,29 +599,31 @@
\let\strc_itemgroups_normal_setup\setupitemgroup
-\unexpanded\def\setupitemgroup
- {\doquadrupleempty\strc_itemgroups_setup}
-
-\def\strc_itemgroups_setup[#category][#levels][#options][#settings]% category level|each options|settings settings|options
- {\edef\strc_itemgroups_setup_what{#levels}%
- \iffourthargument
+\permanent\overloaded\tolerant\protected\def\setupitemgroup[#category]#spacer[#levels]#spacer[#options]#spacer[#settings]% category level|each options|settings settings|options
+ {\ifarguments
+ % nothing to set up
+ \or
+ \edef\strc_itemgroups_setup_what{#levels}%
+ \strc_itemgroups_normal_setup[#category]% == settings
+ \or
+ \edef\strc_itemgroups_setup_what{#levels}%
+ \strc_itemgroups_setup_each{#category}{#levels}%
+ \or
+ \edef\strc_itemgroups_setup_what{#levels}%
\ifx\strc_itemgroups_setup_what\v!each
\strc_itemgroups_setup_each{#category}{#options}%
- \strc_itemgroups_setup_each{#category}{#settings}%
\else
\strc_itemgroups_setup_list{#levels}{#category}{#options}%
- \strc_itemgroups_setup_list{#levels}{#category}{#settings}%
\fi
- \orelse\ifthirdargument
+ \or
+ \edef\strc_itemgroups_setup_what{#levels}%
\ifx\strc_itemgroups_setup_what\v!each
\strc_itemgroups_setup_each{#category}{#options}%
+ \strc_itemgroups_setup_each{#category}{#settings}%
\else
\strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \strc_itemgroups_setup_list{#levels}{#category}{#settings}%
\fi
- \orelse\ifsecondargument
- \strc_itemgroups_setup_each{#category}{#levels}%
- \else
- \strc_itemgroups_normal_setup[#category]% == settings
\fi}
% can be made a bit faster
@@ -663,7 +665,7 @@
\fi
\fi}
-\unexpanded\def\strc_itemgroups_insert_item_counter
+\protected\def\strc_itemgroups_insert_item_counter
{\ifconditional\c_strc_itemgroups_repeat
\ifcase\c_strc_itemgroups_nesting
% skip
@@ -792,11 +794,9 @@
\advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax
\let\currentitemgroup\savedcurrentitemgroup}
-\unexpanded\def\startitemgroup
- {\dotripleempty\strc_itemgroups_start}
-
-\def\strc_itemgroups_start[#category][#options][#settings]%
+\permanent\tolerant\protected\def\startitemgroup[#category]#spacer[#options]#spacer[#settings]%
{\begingroup % (1)
+ \nofarguments\lastarguments
\def\currentitemgroup{#category}% no nested mixing of itemgroups
\let\currentparentitemgroup\currentitemgroup
\global\advance\c_strc_itemgroups_nesting\plusone
@@ -804,22 +804,26 @@
\normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}%
\edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}%
%
- \ifthirdargument
- \strc_itemgroups_start_indeed[#options][#settings]%
- \orelse\ifsecondargument
+ \edef\itemgroupoptions{\itemgroupparameter\c!option}%
+ \let\itemgroupextraoptions\empty
+ \ifcase\nofarguments
+ \strc_itemgroups_start_indeed{}%
+ \or
+ \strc_itemgroups_start_indeed{}%
+ \or
\ifcondition\validassignment{#options}%
- \strc_itemgroups_start_indeed[][#options]%
+ \strc_itemgroups_start_indeed{#options}%
\else
- \strc_itemgroups_start_indeed[#options][]%
+ \edef\itemgroupextraoptions{#options}%
+ \strc_itemgroups_start_indeed{}%
\fi
- \else
- \strc_itemgroups_start_indeed[][]%
+ \or
+ \edef\itemgroupextraoptions{#options}%
+ \strc_itemgroups_start_indeed{#settings}%
\fi}
-\def\strc_itemgroups_start_indeed[#options][#settings]%
- {\edef\itemgroupoptions{\itemgroupparameter\c!option}%
- \edef\itemgroupextraoptions{#options}%
- \ifempty\itemgroupoptions
+\def\strc_itemgroups_start_indeed#settings%
+ {\ifempty\itemgroupoptions
\let\itemgroupoptions\itemgroupextraoptions
\orelse\ifempty\itemgroupextraoptions
% ok
@@ -998,8 +1002,8 @@
% will be redefined in page-mix
\ifdefined\startcolumns \else
- \unexpanded\def\startcolumns[#settings]{}
- \unexpanded\def\stopcolumns {}
+ \protected\def\startcolumns[#settings]{}
+ \protected\def\stopcolumns {}
\fi
\def\strc_itemgroups_start_columns
@@ -1015,7 +1019,7 @@
\fi
-\unexpanded\def\stopitemgroup
+\permanent\protected\def\stopitemgroup
{\stopcollectitems
\ifconditional\c_strc_itemgroups_text
\removeunwantedspaces
@@ -1069,9 +1073,6 @@
% The items.
-\unexpanded\def\startitemgroupitem
- {\dosingleempty\strc_itemgroups_start_item}
-
\def\strc_itemgroups_start_item_first
{\setfalse\c_strc_itemgroups_first
% \begingroup % (3)
@@ -1133,7 +1134,7 @@
% \stopitemize
% \stopitemize
-\unexpanded\def\strc_itemgroups_start_item[#reference]% we can reuse more
+\tolerant\protected\def\startitemgroupitem[#reference]% we can reuse more
{\def\currentitemreference{#reference}%
\ifconditional\c_strc_itemgroups_text
% begin of item
@@ -1171,7 +1172,7 @@
\hskip\d_strc_itemgroups_signal % concat
\itemgroupparameter\c!command}
-\unexpanded\def\stopitemgroupitem
+\protected\def\stopitemgroupitem
{\ifhmode
\endstrut % new per 2017-12-15
\fi
@@ -1180,10 +1181,8 @@
\else
\endgraf
\fi}
-\unexpanded\def\startitemgrouphead
- {\dosingleempty\strc_itemgroups_start_head}
-\unexpanded\def\strc_itemgroups_start_head[#reference]%
+\tolerant\protected\def\startitemgrouphead[#reference]%
{\ifconditional\c_strc_itemgroups_first \else
\strc_itemgroups_insert_breakallow
\fi
@@ -1197,23 +1196,24 @@
\fi
\fi
\fi
- \strc_itemgroups_start_item[#reference]%
+ %\strc_itemgroups_start_item[#reference]%
+ \startitemgroupitem[#reference]%
\pickupgroupedcommand
\strc_itemgroups_start_head_indeed
\strc_itemgroups_stop_head_indeed
\strc_itemgroups_head_body_indeed}
-\unexpanded\def\stopitemgrouphead
+\protected\def\stopitemgrouphead
{\dostoptagged
\stopitemgroupitem}
-\unexpanded\def\strc_itemgroups_start_head_indeed
+\protected\def\strc_itemgroups_start_head_indeed
{\settrue\c_strc_itemgroups_head
\dotagsetitem\s!head% % weird place
\dostarttagged\t!itemhead\empty
\useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces}
-\unexpanded\def\strc_itemgroups_stop_head_indeed
+\protected\def\strc_itemgroups_stop_head_indeed
{\removeunwantedspaces
\dostoptagged
\ifconditional\c_strc_itemgroups_inline_head
@@ -1231,17 +1231,17 @@
\strc_itemgroups_insert_breakno
\fi}
-\unexpanded\def\strc_itemgroups_head_body_indeed
+\protected\def\strc_itemgroups_head_body_indeed
{\dostarttagged\t!itembody\empty
\noindentation
\ignorespaces}
% Simple commands.
-\unexpanded\def\strc_itemgroups_start_do_item
+\protected\def\strc_itemgroups_start_do_item
{\startitemgroupitem}
-\unexpanded\def\strc_itemgroups_start_no_item
+\protected\def\strc_itemgroups_start_no_item
{\let\currentitemreference\empty
\strc_itemgroups_increment_item_counter
%\advance\c_strc_itemgroups_n_of_items\plusone
@@ -1249,27 +1249,27 @@
\strc_itemgroups_check_for_repeated
\ignorespaces}
-\unexpanded\def\strc_itemgroups_start_button[#destination]%
+\protected\def\strc_itemgroups_start_button[#destination]%
{\edef\m_strc_itemgroups_destination{#destination}%
\startitemgroupitem}
-\unexpanded\def\strc_itemgroups_start_symbol#text%
+\protected\def\strc_itemgroups_start_symbol#text%
{\def\strc_itemgroups_extra_symbol{#text}%
\settrue\c_strc_itemgroups_symbol
\startitemgroupitem
\dotagsetitem\s!symbol}
-\unexpanded\def\strc_itemgroups_start_dummy
+\protected\def\strc_itemgroups_start_dummy
{\strc_itemgroups_start_symbol
%\strut\strut} % two ?
\begstrut}
-\unexpanded\def\strc_itemgroups_start_subitem
+\protected\def\strc_itemgroups_start_subitem
{\settrue\c_strc_itemgroups_sub
\startitemgroupitem
\dotagsetitem\s!sub}
-\unexpanded\def\strc_itemgroups_start_edge#text%
+\protected\def\strc_itemgroups_start_edge#text%
{\strc_itemgroups_start_symbol
{\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
\dostarttagged\t!ignore\empty % for the moment, maybe an attribute
@@ -1277,7 +1277,7 @@
{#text\hskip\itemgroupparameter\c!distance}%
\dostoptagged}}
-\unexpanded\def\strc_itemgroups_start_margin#text%
+\protected\def\strc_itemgroups_start_margin#text%
{\def\strc_itemgroups_margin_symbol % brrr
{\dostarttagged\t!ignore\empty % for the moment, maybe an attribute
\llap
@@ -1290,35 +1290,32 @@
\startitemgroupitem
\dotagsetitem\s!margin}
-\unexpanded\def\strc_itemgroups_start_text#text%
+\protected\def\strc_itemgroups_start_text#text%
{\def\strc_itemgroups_extra_symbol{#text}%
\settrue\c_strc_itemgroups_symbol
\settrue\c_strc_itemgroups_txt
\startitemgroupitem}
-% \unexpanded\def\strc_itemgroups_start_head
+% \protected\def\strc_itemgroups_start_head
% {\settrue\c_strc_itemgroups_head
% \startitemgrouphead}
-\unexpanded\def\strc_itemgroups_start_items
+\protected\def\strc_itemgroups_start_items
{\dosingleempty\strc_itemgroups_start_items_indeed}
-\unexpanded\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost
+\protected\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost
{\strc_itemgroups_start_edge
{\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}%
\unskip}}
-% \unexpanded\def\startspecialitemgroupitem[#name]%
-% {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname}
-
-\unexpanded\def\startspecialitemgroupitem[#name]%
+\protected\def\startspecialitemgroupitem[#name]% todo: frozen
{\ifcsname\??itemgroupstart#name\endcsname
\expandafter\lastnamedcs
\else
\expandafter\strc_itemgroups_start_do_item
\fi}
-\unexpanded\def\stopspecialitemgroupitem
+\protected\def\stopspecialitemgroupitem % todo: frozen
{\stopitemgroupitem}
\letvalue{\??itemgroupstart\v!item}\strc_itemgroups_start_do_item
@@ -1329,7 +1326,7 @@
\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text
-\def\optimizelistitemsbreak
+\def\strc_itemgroups_optimize_breaks
{\ifcase\c_strc_itemgroups_column_depth
\ifconditional\c_strc_itemgroups_optimize
\ifcase\c_strc_itemgroups_max_items
@@ -1411,11 +1408,12 @@
\box\b_strc_itemgroups
\hss}} % was: \hfill
-\unexpanded\def\strc_itemgroups_start_head_sym#text%
+\protected\def\strc_itemgroups_start_head_sym#text%
{\def\strc_itemgroups_extra_symbol{#text}%
\settrue\c_strc_itemgroups_symbol
\settrue\c_strc_itemgroups_head
- \strc_itemgroups_start_head}
+ %\strc_itemgroups_start_head}
+ \startitemgrouphead}
\def\strc_itemgroups_make_symbol_box
{\setbox\b_strc_itemgroups\autodirhbox
@@ -1490,7 +1488,7 @@
\par % done twice?
\fi
\advance\c_strc_itemgroups_n_of_items\plusone
- \optimizelistitemsbreak
+ \strc_itemgroups_optimize_breaks
\strc_itemgroups_check_indenting
\dontleavehmode
\ifconditional\c_strc_itemgroups_indented_first
@@ -1551,7 +1549,7 @@
\setvalue\??itemgroupdistance % catches empty value
{\let\m_strc_itemgroups_text_distance\zeropoint}
-\unexpanded\def\strc_itemgroups_set_text_item_distance
+\protected\def\strc_itemgroups_set_text_item_distance
{\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}%
\ifempty\m_strc_itemgroups_text_distance
%
@@ -1569,45 +1567,45 @@
{\interwordspace \s!plus \emwidth}%
{\emwidth \s!plus \interwordstretch\s!minus\interwordshrink}}
-% \unexpanded\def\strc_itemgroups_default_command
+% \protected\def\strc_itemgroups_default_command
% {\EveryPar{\ignorespaces}% needed ?
% \ignorespaces}
-\unexpanded\def\strc_itemgroups_default_command
+\protected\def\strc_itemgroups_default_command
{\ignorespaces}
%D Special case:
-\unexpanded\def\strc_itemgroups_head#text\par
+\protected\def\strc_itemgroups_head#text\par
{\startitemgrouphead{#text}}
%D The local commands:
\appendtoks
- \let\item \strc_itemgroups_start_do_item
- \let\sub \strc_itemgroups_start_subitem
- \let\sym \strc_itemgroups_start_symbol
- \let\ran \strc_itemgroups_start_edge
- \let\its \strc_itemgroups_start_items
- \let\mar \strc_itemgroups_start_margin
- \let\noitem \strc_itemgroups_start_no_item
- \let\itm \strc_itemgroups_start_do_item
- \let\but \strc_itemgroups_start_button
- \let\nop \strc_itemgroups_start_dummy
- \let\txt \strc_itemgroups_start_text
- \let\head \strc_itemgroups_head
- \let\headsym \strc_itemgroups_start_head_sym
- \let\startitem \startitemgroupitem
- \let\stopitem \stopitemgroupitem
- \let\starthead \startitemgrouphead
- \let\stophead \stopitemgrouphead
- \let\startspecialitem\startspecialitemgroupitem
- \let\stopspecialitem \stopspecialitemgroupitem
+ \enforced\let\item \strc_itemgroups_start_do_item
+ \enforced\let\sub \strc_itemgroups_start_subitem
+ \enforced\let\sym \strc_itemgroups_start_symbol
+ \enforced\let\ran \strc_itemgroups_start_edge
+ \enforced\let\its \strc_itemgroups_start_items
+ \enforced\let\mar \strc_itemgroups_start_margin
+ \enforced\let\noitem \strc_itemgroups_start_no_item
+ \enforced\let\itm \strc_itemgroups_start_do_item
+ \enforced\let\but \strc_itemgroups_start_button
+ \enforced\let\nop \strc_itemgroups_start_dummy
+ \enforced\let\txt \strc_itemgroups_start_text
+ \enforced\let\head \strc_itemgroups_head
+ \enforced\let\headsym \strc_itemgroups_start_head_sym
+ \enforced\let\startitem \startitemgroupitem
+ \enforced\let\stopitem \stopitemgroupitem
+ \enforced\let\starthead \startitemgrouphead
+ \enforced\let\stophead \stopitemgrouphead
+ \enforced\let\startspecialitem\startspecialitemgroupitem
+ \enforced\let\stopspecialitem \stopspecialitemgroupitem
\to \itemgroupcommands
\ifx\currentinterface \s!english \else
- \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi}
+ \def\next#1#2{\ifcsname#1\endcsname\else\enforced\expandafter\let\csname#1\endcsname#2\fi}
\etoksapp\itemgroupcommands{%
\next{\v!item }\strc_itemgroups_start_do_item
@@ -1666,10 +1664,6 @@
\newcount\c_strc_itemgroups_collected_done
\newcount\c_strc_itemgroups_collected_current
-% \expandafter\def\expandafter\strc_itemgroups_collected_store\expandafter#\expandafter1\csname\e!stop\v!item\endcsname % use grabuntil
-% {\advance\c_strc_itemgroups_collected_stored\plusone
-% \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}}
-
\let\strc_itemgroups_collected_store\relax
\normalexpanded{\def\strc_itemgroups_collected_store#1\csname\e!stop\v!item\endcsname}%
@@ -1722,7 +1716,7 @@
\expandafter\strc_itemgroups_collected_flush
\fi}
-\unexpanded\def\stopcollectitems
+\protected\def\stopcollectitems % todo: frozen
{\ifconditional\c_strc_itemgroups_collecting
\c_strc_itemgroups_collected_done \zerocount
\c_strc_itemgroups_collected_current\zerocount
@@ -1738,7 +1732,7 @@
\fi
\fi}
-\unexpanded\def\startcollectitems
+\protected\def\startcollectitems % todo: frozen
{\ifconditional\c_strc_itemgroups_collecting
\c_strc_itemgroups_collected_stored\zerocount
\letvalue{\e!start\v!item}\strc_itemgroups_collected_store
@@ -1746,7 +1740,7 @@
%D Left-overs:
-\unexpanded\def\item
+\protected\def\item % todo: frozen
{\strc_itemgroups_item_alone}
\def\strc_itemgroups_item_alone[#category]#text\par
@@ -1754,7 +1748,7 @@
\startitem#text\stopitem
\stopitemgroup}
-\unexpanded\def\head
+\protected\def\head % todo: frozen
{\strc_itemgroups_head_alone}
\def\strc_itemgroups_head_alone[#category]#head\par#body\par
@@ -1762,10 +1756,10 @@
\starthead{#head}#body\stophead
\stopitemgroup}
-\setuvalue{\e!start\v!item}%
+\setuvalue{\e!start\v!item}% todo: frozen
{\startitemgroup[\v!itemize]%
\startitemgroupitem
- \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}}
+ \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}} % todo: frozen
% \def\sym#text%
% {\noindent
@@ -1779,11 +1773,9 @@
%D Something for tables:
-\unexpanded\def\itemtag
- {\dosingleempty\strc_itemgroups_item_tag}
-
-\unexpanded\def\strc_itemgroups_item_tag[#reference]% we can reuse more
- {\def\currentitemreference{#reference}%
+\permanent\tolerant\protected\def\itemtag[#reference]% we can reuse more
+ {% what if empty
+ \def\currentitemreference{#reference}%
\iftrialtypesetting
\strc_counters_save\v_strc_itemgroups_counter
\strc_itemgroups_increment_item_counter
@@ -1888,8 +1880,8 @@
\global\c_strc_itemgroups_column_depth\zerocount
\global\c_strc_itemgroups_nesting \zerocount
\glet\currentitemlevel\!!zerocount
- \unexpanded\def\startitemize{\startitemgroup[\v!itemize:\v!note]}%
- \unexpanded\def\stopitemize {\stopitemgroup}}
+ \enforced\permanent\protected\def\startitemize{\startitemgroup[\v!itemize:\v!note]}%
+ \enforced\permanent\protected\def\stopitemize {\stopitemgroup}}
\let\strc_itemgroups_pop\relax
diff --git a/tex/context/base/mkiv/strc-lab.mkxl b/tex/context/base/mkiv/strc-lab.mkxl
new file mode 100644
index 000000000..2de2b1007
--- /dev/null
+++ b/tex/context/base/mkiv/strc-lab.mkxl
@@ -0,0 +1,198 @@
+%D \module
+%D [ file=strc-lab, % was part of strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Labels,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Labels}
+
+\unprotect
+
+% todo: reset and increment will go
+
+%D Labels are implemented somewhat inefficient but have the advantage that they
+%D can be controlled like other constructions. Who knows when that comes in
+%D handy?
+
+\installcorenamespace{labels}
+
+\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one)
+
+\installcounterassociation{label}
+
+\let\setuplabels\setuplabel
+
+\setuplabel
+ [\c!alternative=\v!intext,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ \c!distance=\zeropoint,
+ \c!width=\v!fit,
+ \c!titledistance=.5\emwidth,
+ \c!margin=\v!no,
+ \c!titleleft=(,
+ \c!titleright=),
+ \c!display=\v!no,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ \c!text=\currentlabel,
+ \c!number=\v!yes, % else description
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=3]
+
+\protected\def\strc_define_commands_label#1#2#3% current level parent
+ {\doifelsenothing{#3}
+ {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label}}%
+ {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label#3}}%
+ \ifconditional\c_strc_constructions_define_commands
+ \setuevalue{\e!next #1}{\strc_labels_next {#1}{\number#2}}% obsolete
+ \setuevalue{\v!reset #1}{\strc_labels_reset {#1}{\number#2}}% obsolete % should be \e!reset anyway
+ %setuevalue{\c!set #1}{\strc_labels_set {#1}{\number#2}}% obsolete
+ \ifcsname\v!current#1\endcsname
+ % we play safe
+ \else
+ \setuevalue{\v!current#1}{\strc_labels_current{#1}}% % obsolete % should be \e!current anyway
+ \fi
+ \setuevalue{#1}{\strc_labels_command[#1]}%
+ \fi}
+
+% todo: \strc_labels_command for user
+
+\appendtoks
+ \ifx\currentlabelparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentlabelsub\empty
+ \strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \plusone
+ \empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_label
+ {\v!sub\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabel}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentlabelsub\empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabelparent}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
+ \fi
+ \edef\p_counter{\labelparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentlabel
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_labels_define_counter\p_counter}%
+ \letlabelparameter\s!counter\p_counter
+\to \everydefinelabel
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\newconditional\c_strc_constructions_number_keep
+
+\setvalue{\??constructioninitializer\v!label}%
+ {\let \currentlabel \currentconstruction
+ \enforced\let\constructionparameter \labelparameter
+ \enforced\let\constructionnamespace \??label
+ \enforced\let\detokenizedconstructionparameter\detokenizedlabelparameter
+ \enforced\let\letconstructionparameter \letlabelparameter
+ \enforced\let\useconstructionstyleandcolor \uselabelstyleandcolor
+ \enforced\let\setupcurrentconstruction \setupcurrentlabel
+ % shared with enumerations
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ \ifconditional\c_strc_constructions_number_keep \else
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\setvalue{\??constructionfinalizer\v!label}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Interfaces:
+
+\protected\def\strc_labels_command{\setfalse\c_strc_constructions_number_keep\strc_descriptions_command}
+\protected\def\strc_labels_current{\settrue \c_strc_constructions_number_keep\strc_descriptions_command}
+
+\protected\def\strc_labels_next {\strc_constructions_next_indeed \namedlabelparameter} % #1#2
+\protected\def\strc_labels_reset {\strc_constructions_reset_indeed\namedlabelparameter} % #1#2
+%protected\def\strc_labels_set {\strc_constructions_set_indeed \namedlabelparameter} % #1#2
+
+% similar to enumerations
+
+\def\strc_labels_define_counter#1%
+ {\definecounter[#1]%
+ \registerlabelcounter{#1}}
+
+\appendtoks
+ \synchronizelabelcounters
+\to \everysetuplabel
+
+\appendtoks
+ \synchronizelabelcounters
+\to \everydefinelabel
+
+% no start stop here
+
+\expandafter\let\csname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname
+
+\protected\setevalue{\??constructioncommandhandler\v!label}%
+ {\csname\??constructionstarthandler\v!construction\endcsname
+ \csname\??constructionstophandler \v!construction\endcsname
+ \endgroup}
+
+\protected\setvalue{\??constructiontexthandler\v!label}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_labels_text
+ \endgroup}
+
+\let\strc_labels_text\strc_enumerations_text
+
+% inline variant
+
+\defineconstructionalternative
+ [\v!intext]
+ [\c!renderingsetup=\??constructionrenderings:\v!intext]
+
+\startsetups[\??constructionrenderings:\v!intext]
+ \dontleavehmode\box\constructionheadbox
+\stopsetups
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-lst.mkvi b/tex/context/base/mkiv/strc-lst.mkvi
index 678c02e15..7a593878c 100644
--- a/tex/context/base/mkiv/strc-lst.mkvi
+++ b/tex/context/base/mkiv/strc-lst.mkvi
@@ -892,7 +892,7 @@
\appendtoks
% better is to use a special list entry but we keep this for compatibility
- \let\\=\space
+ \enforced\let\\\space
% so expanding this token register has to come *after* the font switch
\dontconvertfont % (**) this has to become an option (see publ)
\to \t_lists_every_renderingtext
diff --git a/tex/context/base/mkiv/strc-mat.mkiv b/tex/context/base/mkiv/strc-mat.mkiv
index fe25e236e..7f5a19154 100644
--- a/tex/context/base/mkiv/strc-mat.mkiv
+++ b/tex/context/base/mkiv/strc-mat.mkiv
@@ -499,6 +499,8 @@
%D
%D Otherwise we get a missing \type {$$} error reported.
+\pushoverloadmode
+
\let\reqno\eqno % no longer valid as we just nil it
\let\math_native_leqno\leqno
@@ -513,6 +515,8 @@
\let\reqno\normaleqno
\let\eqno \normaleqno
+\popoverloadmode
+
%D \macros
%D {startsubformulas}
diff --git a/tex/context/base/mkiv/strc-not.mklx b/tex/context/base/mkiv/strc-not.mklx
new file mode 100644
index 000000000..6e82c9c4e
--- /dev/null
+++ b/tex/context/base/mkiv/strc-not.mklx
@@ -0,0 +1,1972 @@
+%D \module
+%D [ file=strc-not,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Note Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Note Handling}
+
+\registerctxluafile{strc-not}{}
+
+\unprotect
+
+% todo: finish local rendering
+% todo: more p_strc_notations_* (outside trial loop)
+% todo: see if we can now use \insertpenalties (>0 == some left)
+
+\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi
+\ifdefined\dotagsetnotation \else \let\dotagsetnotation \relax \fi
+
+\protected\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often
+\protected\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often
+
+%D \LMTX\ testcase:
+%D
+%D \starttyping
+%D \hbox {\hbox{\footnote{HH1}\footnote{HH2}}} \par
+%D \hbox {\hbox{x\footnote{XHH1}x\footnote{XHH2}}} \par
+%D \vbox {\setbox0\hbox{\footnote{VH1}\footnote{VH2}}\box0} \par
+%D \vbox {\hbox{\footnote{VH1}xxx\footnote{VH2}}} \par
+%D \vbox {\hbox{\footnote{VH1}\footnote{VH2}}
+%D \hbox{\footnote{VH1}\footnote{VH2}}} \par
+%D \vbox {\hbox{x\footnote{XVH1}x\footnote{XVH2}}} \par
+%D \vbox {\vbox{\footnote{VV1}\footnote{VV2}}} \par % two lines
+%D \vbox {\vbox{x\footnote{XVV1}x\footnote{XVV2}}} \par
+%D \stoptyping
+
+%D Notes have two handlers: notations and notes. Although notations can be defined
+%D independently it makes not much sense. In principle we can treat notes as lists
+%D but they are currently done as a variant on enumerations. I will provide a list
+%D variant as well. One complication is that for page related notes inserts are used
+%D and therefore notes are typeset immediately and descriptions are better suited
+%D for that. For instance endnotes can as well be typeset using lists.
+
+% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number
+
+%D \macros
+%D {setupnote,setupnotation}
+%D
+%D We can influence footnote typesetting with the setup command:
+%D
+%D \showsetup{setupnotation}
+%D \showsetup{setupnote}
+%D
+%D The definition command indicate that we can frame the footnote area. The
+%D footnotes themselves are treated as descriptions.
+%D
+%D \showsetup{definenote}
+%D
+%D It's sort of a custom to precede footnotes by a horizontal rule and although
+%D fancy rules like
+%D
+%D \starttyping
+%D \hbox to 10em{\hskip-3em\dotfill}
+%D \stoptyping
+%D
+%D Are quite ligitimate, we default to a simple one 20\% of the text width.
+
+% \c!headstyle=\noteparameter\c!style,
+% \c!headcolor=\noteparameter\c!color,
+
+\installcorenamespace{notation}
+
+\installcommandhandler \??notation {notation} \??notation
+
+\installcounterassociation{notation}
+
+\aliased\let\setupnotations\setupnotation
+
+\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}]
+\definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}]
+
+\setupnotations % check with old
+ [\c!alternative=\v!note,
+ %\c!headstyle=,
+ %\c!titlestyle=,
+ %\c!style=,
+ %\c!color=,
+ %\c!headcolor=,
+ %\c!titlecolor=,
+ \c!numbercommand=\high,
+ %\c!symbolcommand=\lowllap, % experiment
+ %\c!indicator=\v!no, % was \v!yes in mkii for page notes
+ \c!width=\v!fit,
+ \c!titledistance=.5em,
+ \c!distance=.5em,
+ %\c!hang=,
+ %\c!sample=,
+ %\c!align=,
+ %\c!headalign=,
+ \c!margin=\v!no,
+ \c!before=,
+ \c!inbetween=,
+ \c!after=,
+ \c!indentnext=\v!yes,
+ \c!indenting=\v!never,
+ \c!titleleft=(,
+ \c!titleright=),
+ %\c!closesymbol=,
+ \c!closecommand=\wordright,
+ \c!display=\v!yes,
+ %\c!command=,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ %\c!xmlsetup=,
+ %\s!catcodes=,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ %\c!starter=,
+ %\c!stopper=,
+ \c!number=\v!yes,
+ \c!text=,
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=3]
+
+%D The code here is mostly the same as enumerations but we want to keep them
+%D isolated and at some point we might differentiate.
+
+% \installcorenamespace{noteclass}
+
+\protected\def\strc_define_commands_notation#tag#level#parent%
+ {\doifelsenothing{#parent}
+ {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??notation#tag:\s!parent}{\??notation}}%
+ {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??note #tag:\s!parent}{\??note#parent}% see later for \s!note
+ \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}%
+ \instance\setuevalue{\e!next #tag}{\strc_notations_next {#tag}{\number#level}}% obsolete
+ \instance\setuevalue{\c!reset#tag}{\strc_notations_reset {#tag}{\number#level}}% obsolete
+ \instance\setuevalue {#tag}{\strc_notations_command[#tag]}%
+ \instance\setuevalue{\e!start#tag}{\strc_notations_start [#tag]}%
+ \instance\setuevalue{\e!stop #tag}{\strc_notations_stop }}
+
+\appendtoks
+ \ifx\currentnotationparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentnotationsub\empty
+ \strc_define_commands_notation
+ {\currentnotationsub\currentnotation}%
+ \plusone
+ \empty
+ \edef\p_levels{\notationparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_notation
+ {\v!sub\currentnotationsub\currentnotation}%
+ \recurselevel
+ {\currentnotationsub\currentnotation}%
+ \edef\currentnotationsub{\v!sub\currentnotationsub}}%
+ \definelist[\currentnotation]% goodie
+ \else
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentnotationsub\empty
+ \edef\p_levels{\notationparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_notation
+ {\currentnotationsub\currentnotation}%
+ \recurselevel
+ {\currentnotationsub\currentnotationparent}%
+ \edef\currentnotationsub{\v!sub\currentnotationsub}}%
+ \definelist[\currentnotation][\currentnotationparent]% goodie
+ \fi
+ \edef\p_counter{\notationparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentnotation
+ \fi
+ \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}%
+ \letnotationparameter\s!counter\p_counter
+ %\strc_notes_setup_counter\currentnotation
+\to \everydefinenotation
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\protected\setvalue{\??constructioninitializer\v!notation}%
+ {\let \currentnotation \currentconstruction
+ \enforced\let\constructionparameter \notationparameter
+ \enforced\let\constructionnamespace \??notation
+ \enforced\let\detokenizedconstructionparameter\detokenizednotationparameter
+ \enforced\let\letconstructionparameter \letnotationparameter
+ \enforced\let\useconstructionstyleandcolor \usenotationstyleandcolor
+ \enforced\let\setupcurrentconstruction \setupcurrentnotation
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ %\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\protected\setvalue{\??constructionfinalizer\v!notation}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Notations (we simply needed a word that relates to notes and is and sounds like
+%D description and enumeration) are a special case in the sense that they are
+%D stored, rendered elsewhere and referered to from where they are specified. For
+%D that reason they have a different set op main commands.
+
+% \notation[ref]{title}
+% \notation[reference=,title=]
+% \startnotation[ref] title \stopnotation
+
+\protected\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2
+\protected\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2
+%protected\def\strc_notations_set {\strc_constructions_set_indeed \namednotationparameter} % #1#2
+
+\newconditional\c_strc_notations_anchored_next
+
+\def\strc_notations_finalize
+ {\ifconditional\c_strc_notations_anchored_next
+ \expandafter\strc_notations_finalize_next
+ \else
+ \expandafter\strc_notations_finalize_previous
+ \fi}
+
+\def\strc_notations_finalize_previous
+ {\normalexpanded{\endgroup\noteparameter\c!next}}
+
+\def\strc_notations_finalize_next
+ {\endgroup\ignorespaces}
+
+\tolerant\protected\def\strc_notations_command[#1]#*[#2]%
+ {\begingroup
+ \edef\currentnote{#1}%
+ \strc_constructions_initialize{#1}%
+ \strc_notes_synchronize
+ \edef\p_next{\noteparameter\c!anchor}%
+ \ifx\p_next\v!next % for now only two states
+ \settrue \c_strc_notations_anchored_next
+ \else
+ \setfalse\c_strc_notations_anchored_next
+ \fi
+ \ifnotesenabled
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \ifhastok={#2}%
+ \expandafter\strc_notations_command_setups
+ \else
+ \expandafter\strc_notations_command_reference
+ \fi[#2]}
+
+\def\strc_notations_command_setups[#1]%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]%
+ \strc_notations_wrapup}
+
+\tolerant\def\strc_notations_command_reference[#1]#*#=%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \strc_notations_wrapup}
+
+\def\strc_notations_wrapup
+ {\csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \strc_notations_finalize}
+
+\tolerant\protected\def\strc_notations_start[#1]#*[#2]%
+ {\begingroup
+ \edef\currentnote{#1}%
+ \strc_constructions_initialize{#1}%
+ \strc_notes_synchronize
+ \ifnotesenabled
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \fi
+ \ifhastok={#2}%
+ \expandafter\strc_notations_start_setups
+ \else
+ \expandafter\strc_notations_start_reference
+ \fi[#2]}
+
+\protected\def\strc_notations_start_setups[#1]%
+ {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_setups_indeed[#1]{##1}}}%
+ \strc_pickup_yes}
+
+\protected\def\strc_notations_start_setups_indeed[#1]#*#2%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#2},\c!bookmark=,\c!list=,#1]%
+ \strc_notations_wrapup}
+
+\protected\def\strc_notations_start_reference[#1]%
+ {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_reference_indeed[#1]{##1}}}%
+ \strc_pickup_yes}
+
+\protected\def\strc_notations_start_reference_indeed[#1]#*#2%
+ {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]%
+ \strc_notations_wrapup}
+
+\protected\def\strc_notations_stop
+ {}
+
+%D A complication is that we need to set up rather specific properties of e.g.
+%D footnotes. It is for this reason that we introduce an extra level of
+%D indirectness. This way notations don't bark on undefined macros when used in
+%D combination.
+
+\protected\setvalue{\??constructionnotehandler\v!notation}%
+ {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname}
+
+\protected\setvalue{\??constructionnotehandler\v!notation:}% empty case
+ {[\currentconstructionhandler:\currentconstruction]}
+
+%D Here is a simple renderer for notes
+
+\defineconstructionalternative
+ [\v!note]
+ [\c!renderingsetup=\??constructionrenderings:\v!note]
+
+\startsetups[\??constructionrenderings:\v!note]
+ \noindent
+ \leftboundary % experiment, to be done in more places
+ \llap{\box\constructionheadbox\hskip\constructionparameter\c!distance}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+%D We now implement the note definer.
+
+\installcorenamespace{note}
+
+\installframedcommandhandler \??note {note} \??note
+
+\let\setupnotes\setupnote
+
+% These only concern the inline symbol/number and wrapping of the whole list.
+
+\setupnotes % not all make sense here
+ [\c!location=\v!page,
+ %\c!conversion=,
+ \c!rule=\v!on,
+ \c!before=\blank,
+ \c!bodyfont=\v!small,
+ \c!anchor=, % can also be v!next
+ %\c!style=,
+ %\c!color=,
+ %\c!after=,
+ %\c!rulecolor=,
+ %\c!rulecommand=,
+ \c!rulethickness=\linewidth,
+ \c!frame=\v!off,
+ \c!distance=.125em, % in the text between symbols
+ % \c!textseparator={,}, % optional separator
+ \c!columndistance=1em,
+ % \c!margindistance=.5em,
+ \c!align=, % also use instead of \c!tolerance
+ \c!split=\v!tolerant,
+ \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi
+ \c!height=\textheight,
+ \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice
+ \c!separator=,%
+ \c!textcommand=\high,
+ \c!textstyle=\tx,
+ %\c!textcolor=,
+ \c!interaction=\v!yes,
+ %\c!factor=,
+ %\c!scope=, % \v!text \v!page
+ \c!prefixconnector=.,
+ %\c!next=\autoinsertnextspace,
+ \c!prefix=\v!no,
+ %\c!continue=\v!no,
+ \c!paragraph=\v!no,
+ \c!inbetween=\hskip\emwidth,
+ \c!symbol=\mathematics{*},
+ \c!n=1]
+
+\setupnotes
+ [\c!expansion=\v!no,
+ \c!xmlsetup=,
+ \s!catcodes=]
+
+%D Insertions are part of notes.
+
+% \installcorenamespace{noteinsertion}
+
+\permanent\def\currentnoteinsertion {\noteparameter\s!insert}
+\permanent\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}}
+
+\appendtoks
+ \ifx\currentnoteparent\empty
+ \doifelseinsertion\currentnote
+ \donothing
+ {\defineinsertion[\currentnote]% could be an option
+ \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}%
+ \letnoteparameter\s!insert\currentnote
+ \definenotation[\currentnote][\c!type=\v!note]%
+ \else
+ \setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}%
+ \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
+ \fi
+ \clf_definenote
+ {\currentnote}%
+ {insert}%
+ \currentnoteinsertionnumber
+ \relax
+\to \everydefinenote
+
+% maybe we will share this at some point:
+
+\def\strc_notes_define_counter#tag% todo: move inline
+ {\definecounter[#tag]%
+ \registerenumerationcounter{#tag}}
+
+\appendtoks
+ \synchronizenotationcounters
+\to \everysetupnotation
+
+\appendtoks
+ \synchronizenotationcounters
+\to \everydefinenotation
+
+% so far
+
+%expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname
+\expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess
+\expandafter\let\csname\??constructionstophandler \v!notation\expandafter\endcsname\csname\??constructionstophandler \v!enumeration \endcsname
+\expandafter\let\csname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname
+\expandafter\let\csname\??constructiontexthandler \v!notation\expandafter\endcsname\csname\??constructiontexthandler \v!enumeration \endcsname
+
+\protected\setvalue{\??constructionmainhandler\v!notation}#following%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize
+ \c_attr_destination\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#following}
+
+\protected\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text
+ {\ifnotesenabled
+ % do be done elsewhere
+ %
+ %let\currentnote\currentconstructionmain
+ \let\currentnote\currentconstruction % else wrong inheritance
+ %
+ \iftrialtypesetting
+ \strc_notes_inject_dummy
+ \else
+ \begingroup
+ \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}%
+ \settrue\processingnote
+ \ifconditional\c_strc_notes_skip
+ \glet\lastnotesymbol\strc_notes_inject_symbol_nop
+ \else
+ \iftypesettinglines % otherwise problems with \type <crlf> {xxx}
+ \ignorelines % makes footnotes work in \startlines ... \stoplines
+ \fi
+ \ifconditional\c_strc_notes_symbol
+ \strc_notes_inject_symbol_yes
+ \else
+ \unskip\unskip
+ \glet\lastnotesymbol\strc_notes_inject_symbol_yes
+ \fi
+ \fi
+ \ifconditional\postponingnotes % todo: per note class
+ \global\settrue\postponednote
+ \orelse\ifconditional\inlocalnotes % todo: per note class
+ \global\settrue\postponednote
+ \orelse\ifconditional\c_strc_notes_delayed
+ % probably end notes
+ \else
+ \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed
+ \fi
+ \endgroup
+ \fi
+ \fi
+ \ifconditional\c_strc_notes_skip
+ \global\setfalse\c_strc_notes_skip
+ \else
+ \kern\notesignal\relax % \relax is needed to honor spaces
+ \fi}
+
+%D Interaction in notes is somewhat complex due to the way notes get flushed. In
+%D principle it is more or less the same as lists but where in lists we pack whole
+%D entries, in notes this doesn't happen. Okay, in retrospect we could have made
+%D descriptions lists but that will be a backward compatibility mess. At some point
+%D a completely new mechanism might show up, but not now. Also, as notes are inserts
+%D there is some extra mess to be kept in mind and it's easier to maintain two
+%D mechanisms than to combine too much.
+%D
+%D Interaction is also complicated because we want to provide several variants. For
+%D simple reference there is no need for anything special, as page references will
+%D do and we store them in the list anyway. But if we want a destination with
+%D dimensions we will use an additional destination because we can have only one
+%D with the same name and we always have the number as one.
+
+% interaction:
+%
+% all : text and number
+% number|yes: only number
+% text : only text
+%
+% \dogetsimple : injects
+
+\installcorenamespace{noteinteractioninline}
+\installcorenamespace{noteinteractiondisplay}
+
+\newconstant\a_strc_notes_symbol_reference
+\newconstant\a_strc_notes_number_reference
+\newconstant\a_strc_notes_text_reference
+\newconstant\a_strc_notes_text_destination
+
+\let\strc_notes_get_reference_attribute_symbol \empty
+\let\strc_notes_get_destination_attribute_symbol\empty
+
+\def\strc_notes_interaction_check_inline
+ {\edef\p_interaction{\noteparameter\c!interaction}%
+ \csname\??noteinteractioninline
+ \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi
+ \endcsname}
+
+\def\strc_notes_interaction_check_display
+ {\edef\p_interaction{\noteparameter\c!interaction}%
+ \csname\??noteinteractiondisplay
+ \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi
+ \endcsname}
+
+\def\currentnotenumber{0}
+
+\let\strc_notes_get_reference_attribute_symbol \empty
+\let\strc_notes_get_destination_attribute_symbol\empty
+
+\let\strc_notes_set_reference_attribute_number\donothing
+\let\strc_notes_set_reference_attribute_text \donothing
+\let\strc_notes_set_destination_attribute_text\donothing
+
+% inline
+
+\def\strc_references_prepare_inline_references_nop
+ {\let\strc_notes_get_reference_attribute_symbol\empty
+ \let\strc_notes_get_destination_attribute_symbol\empty
+ \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop}
+
+% \def\strc_references_prepare_inline_references_yes
+% {\strc_references_set_simple_reference{symb:\currentnote:\currentnotenumber}% destination
+% \strc_references_get_simple_reference{internal(\clf_noteinternal{\currentnote}\currentnotenumber)}% reference
+% \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
+% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+% \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
+
+\def\strc_references_prepare_inline_references_yes
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \strc_references_set_simple_reference{*\currentnoteinternal}% destination
+ \strc_references_get_simple_reference{internal(\currentnoteinternal)}% reference
+ \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
+ \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
+
+\letvalue{\??noteinteractioninline\v!no }\strc_references_prepare_inline_references_nop
+\letvalue{\??noteinteractioninline\v!all }\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!number}\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!text }\strc_references_prepare_inline_references_yes
+\letvalue{\??noteinteractioninline\v!yes }\strc_references_prepare_inline_references_yes
+
+% display (for 'all' we need unique text and number attributes so we resolve twice
+% as we otherwise don't get the number one which is lapped in the margin so we need
+% to explicitly visit it)
+
+\def\strc_references_prepare_display_references_nop
+ {\let\strc_notes_set_reference_attribute_number\donothing
+ \let\strc_notes_set_reference_attribute_text\donothing
+ \let\strc_notes_set_destination_attribute_text\donothing
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop}
+
+\def\strc_references_prepare_display_references_yes_number
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \let\strc_notes_set_reference_attribute_text\donothing
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\def\strc_references_prepare_display_references_yes_text
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
+ \let\strc_notes_set_reference_attribute_number\donothing
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\def\strc_references_prepare_display_references_yes_all
+ {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}%
+ \ifcase\currentnoteinternal\relax
+ \strc_references_prepare_display_references_nop
+ \else
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
+ \strc_references_get_simple_reference{*\currentnoteinternal}% reference
+ \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}%
+ \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
+ \fi}
+
+\letvalue{\??noteinteractiondisplay\v!no }\strc_references_prepare_display_references_nop
+\letvalue{\??noteinteractiondisplay\v!all }\strc_references_prepare_display_references_yes_all
+\letvalue{\??noteinteractiondisplay\v!number}\strc_references_prepare_display_references_yes_number
+\letvalue{\??noteinteractiondisplay\v!text }\strc_references_prepare_display_references_yes_text
+\letvalue{\??noteinteractiondisplay\v!yes }\strc_references_prepare_display_references_yes_number
+
+\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor
+\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor
+
+\protected\def\strc_notes_set_style_color_inline_yes#style#color%
+ {\usenotestyleandcolor#style#color%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\protected\def\strc_notes_set_style_color_display_yes#style#color%
+ {\usenotationstyleandcolor#style#color%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\def\strc_notes_set_style_color_special
+ {\iftrialtypesetting
+ % keep
+ \orelse\ifx\currentcolorparameter\empty
+ \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once
+ \setlocationcolorspecified\scratchcounter
+ \fi}
+
+\setvalue{\??constructiontexthandler\v!notation}%
+ {\begingroup
+ % we need to retrigger the reference as otherwise it gets lost because we don't do nested
+ % references with the same id ... maybe some day if we can figure out a nice heuristic ...
+ % the problem is that normally it's no issue but here we lap into the margin, so maybe that's
+ % a criterium
+ % \strc_notes_interaction_check_display
+ \strc_notes_set_reference_attribute_number
+ \dotagsetnotation
+ \strc_notes_set_style_color_display\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+% in mkii the pointer only showed up in pagewise notes
+
+\protected\def\strc_notes_inject_pointer % todo calculate once
+ {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax
+ % unknown
+ \or
+ % same page
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}%
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}%
+ \fi}
+
+\protected\def\strc_notes_inject_symbol_yes
+ {\strc_notes_inject_symbol_indeed\conditionaltrue}
+
+\protected\def\strc_notes_inject_symbol_nop
+ {\strc_notes_inject_symbol_indeed\conditionalfalse}
+
+\definemargindata
+ [strc_notes_destination_margin]
+ [\v!left]
+ [\c!margin=\zeropoint,
+ \c!width=\zeropoint,
+ \c!style=,
+ \c!color=]
+
+\protected\def\strc_notes_inject_symbol_indeed#synchronize%
+ {\ifconditional\c_strc_notations_anchored_next\else
+ \removeunwantedspaces
+ \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
+ \fi
+ \ifdim\lastkern=\notesignal
+ % \kern\noteparameter\c!distance % yes or no note font? or main text
+ \strc_notes_inject_separator
+ \fi
+ \nobreak
+ \begingroup
+ \strc_notes_interaction_check_inline
+ \strc_notes_set_style_color_inline\c!textstyle\c!textcolor
+ \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup
+ % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack
+ \strc_references_flush_destination_nodes % a bit late but ok
+ \dostarttagged\t!descriptionsymbol\currentnote
+ \dotagsetnotesymbol
+ \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}%
+ % the next one can cycle so we need to make sure it has no advance width
+ \doif{\noteparameter\c!indicator}\v!yes\strc_notes_inject_pointer
+ \dostoptagged
+ \egroup
+ \endgroup
+ \glet\lastnotesymbol\relax}
+
+\protected\def\strc_notes_inject_dummy % temp hack
+ {\removeunwantedspaces
+ \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
+ \ifdim\lastkern=\notesignal
+ % \kern\noteparameter\c!distance % yes or no note font? or main text
+ \strc_notes_inject_separator
+ \fi
+ \nobreak
+ \hpack to .5\emwidth{}%
+ \glet\lastnotesymbol\relax}
+
+\protected\def\strc_notes_inject_separator % patch by WS due to request on list
+ {\edef\p_textseparator{\noteparameter\c!textseparator}%
+ \ifx\p_textseparator\empty
+ \kern\noteparameter\c!distance
+ \else
+ % skip or kern
+ \nobreak
+ \hbox\bgroup
+ \strc_notes_interaction_check_inline
+ \strc_notes_set_style_color_inline\c!textstyle\c!textcolor
+ \noteparameter\c!textcommand{\p_textseparator}%
+ \kern\noteparameter\c!distance
+ \egroup
+ \nobreak
+ \fi}
+
+% this needs a further cleanup ... soon as it's a slow mechanism
+%
+% -- set breakpoint in descriptions
+% -- reset after trialtypesetting
+% -- that way we can trick the symbol space
+
+% removed:
+%
+% \pushsomestates
+%
+% core-ins -> obsolete
+%
+% saveinsertiondata
+% restoreinsertiondata
+% saveinsertionbox
+% eraseinsertionbackup
+% restoreinsertionbackup
+
+\def\savenotedata {} % \writestatus{todo}{save note data}}
+\def\restorenotedata {} % \writestatus{todo}{restore note data}}
+\def\savenotecontent {} % \writestatus{todo}{save note content}}
+\def\restorenotecontent{} % \writestatus{todo}{restore note content}}
+\def\erasenotebackup {} % \writestatus{todo}{erase note backup}}
+
+% page-set:
+
+\def\enablenotes {\writestatus{todo}{enable notes}}
+\def\disablenotes {\writestatus{todo}{disable notes}}
+\def\savenotes {\writestatus{todo}{save notes}}
+\def\flushsavednotes{\writestatus{todo}{flush notes}}
+
+% experiment: (compare scope=text and scope=page)
+%
+% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0]
+% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
+
+%D Footnotes are can be characterized by three components:
+%D
+%D \startitemize[packed]
+%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes
+%D [conversion=set 2]\footnote {a footnote}}
+%D \item and a similar mark at the bottom of the page
+%D \item followed by some additional text
+%D \stopitemize
+%D
+%D Because footnotes are declared at the location of their reference they can be
+%D seen as a special kind of floating bodies. Their placement is postponed but has
+%D to be taken into account in the pagebreak calculations. This kind of calculations
+%D are forced by using \type{\insert}s and dealing with all cases is not trivial.
+
+%D \macros
+%D {notesenabled}
+%D
+%D We need a couple of states because at some moments we don't want to mess around
+%D with inserts at all. Take for instance a table of contents. And so we can
+%D temporary disable footnotes by saying
+%D
+%D \starttyping
+%D \notesenabledfalse
+%D \stoptyping
+
+\newif\ifnotesenabled \notesenabledtrue
+
+% better mark a note .. once flushed no more flushing
+
+%appendtoks \notesenabledfalse \to \everymarking
+\appendtoks \notesenabledfalse \to \everybeforepagebody
+\appendtoks \notesenabledfalse \to \everystructurelist % quick hack
+\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack
+\appendtoks \notesenabledfalse \to \everypreroll % quick hack
+
+%D Often we need to process the whole set of notes and to make that fast, we use a
+%D token register:
+
+% we have several synchronizers:
+%
+% - after a definition
+% - after a specific setup
+% - after a general setup (inheritance of dimensions)
+% - just before a note is typeset
+
+\newtoks\t_strc_notes
+
+\let\strc_notes_process_list\gobbleoneargument
+
+\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote
+ {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}%
+ \the\t_strc_notes}
+
+\newtoks\everychecknote % just before a note is typeset
+\newtoks\everysynchronizenote % after a general setup has happened
+
+\appendtoks
+ \ifx\currentnote\empty \else
+ \setupnotations[\currentnote][]% also a synchronize
+ \fi
+\to \everysynchronizenote
+
+\def\strc_notes_synchronize
+ {\the\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist
+
+\appendtoks
+ \strc_notes_process\strc_notes_synchronize
+\to \everysetupnoteroot
+
+\appendtoks
+ \the\everysynchronizenote
+\to \everydefinenote
+
+% \starttext
+% text \startfootnote Test.\stopfootnote
+% test \footnote{xxxx} \subfootnote{xxxx}
+% test \footnote{xxxx} \subfootnote{xxxx}
+% \stoptext
+
+\installcorenamespace{notecommand}
+\installcorenamespace{notealign}
+\installcorenamespace{notepenalty}
+\installcorenamespace{noterule}
+
+\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname}
+\permanent\protected\def\currentnoterulealign {\begincsname\??notealign \currentnote\endcsname}
+
+\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand}
+\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards
+
+\permanent\protected\def\letcurrentnoterulecommand{\enforced\expandafter\let\csname\??notecommand\currentnote\endcsname}
+\permanent\protected\def\letcurrentnoterulealign {\enforced\expandafter\let\csname\??notealign \currentnote\endcsname}
+
+\appendtoks
+ \enforced\expandafter\let\csname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal
+ \enforced\expandafter\let\csname\??notealign \currentnote\endcsname\lefttoright
+\to \everysynchronizenote
+
+\def\strc_notes_set_rule
+ {\letcurrentnoterulecommand\relax % so we default to nothing
+ \letcurrentnoterulealign \relax
+ \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step}
+
+\def\strc_notes_set_rule_step#alternative%
+ {\begincsname\??noterule#alternative\endcsname}
+
+\def\strc_notes_set_rule_autodir
+ {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright}
+
+\setvalue{\??noterule \v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand}
+\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!left}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \lefttoright}
+\setvalue{\??noterule \v!right}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \righttoleft}
+\setvalue{\??noterule\v!paragraph}{\letcurrentnoterulecommand\currentnoterulecommandnormal
+ \letcurrentnoterulealign \strc_notes_set_rule_autodir}
+\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax}
+
+\appendtoks
+ \strc_notes_set_rule
+\to \everysynchronizenote
+
+\permanent\def\currentnotepenalty
+ {\ifcsname\??notepenalty\noteparameter\c!split\endcsname
+ \lastnamedcs
+ \else
+ \numexpr\noteparameter\c!split\relax
+ \fi}
+
+\setnewconstant\notepenaltytolerant \zerocount
+\setnewconstant\notepenaltystrict 9999
+\setnewconstant\notepenaltyverystrict\maxdimen
+
+\letvalue{\??notepenalty\v!tolerant }\notepenaltytolerant
+\letvalue{\??notepenalty\v!strict }\notepenaltystrict
+\letvalue{\??notepenalty\v!verystrict}\notepenaltyverystrict
+\letvalue{\??notepenalty }\notepenaltytolerant
+
+%D The following switch can be used to disable limiting the height of the footnote
+%D area, something that is needed in multi column balancing. Use this switch with
+%D care.
+
+\newif\ifnotelimit \notelimittrue % shared
+
+\def\strc_notes_set_factor
+ {\edef\p_factor{\noteparameter\c!factor}%
+ \ifx\p_factor\empty \else
+ \ifnum\p_factor<\zerocount \else
+% \global
+ \count\currentnoteinsertionnumber\p_factor % new: global
+ \fi
+ \fi}
+
+\appendtoks
+ \strc_notes_set_factor
+\to \everysynchronizenote
+
+% locations:
+
+\installcorenamespace{notelocationvariant}
+\installcorenamespace{notepositionvariant}
+\installcorenamespace{notedelayedvariant}
+\installcorenamespace{notelocation}
+
+\newconditional\c_strc_notes_delayed
+
+\protected\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed}
+\protected\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed}
+
+\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page}
+\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns}
+\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn}
+\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn}
+\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none}
+\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text}
+\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high}
+\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom}
+
+\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let
+\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let
+\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let
+
+\protected\def\strc_notes_set_delayed
+ {\csname\??notedelayedvariant
+ \ifcsname\??notedelayedvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notedelayedvariant
+ \fi
+ \endcsname}
+
+\protected\def\strc_notes_set_position
+ {\csname\??notepositionvariant
+ \ifcsname\??notepositionvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notepositionvariant
+ \fi
+ \endcsname}
+
+\protected\def\strc_notes_set_location
+ {\csname\??notelocationvariant
+ \ifcsname\??notelocationvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notelocationvariant
+ \fi
+ \endcsname}
+
+\protected\def\strc_notes_set_variants
+ {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
+
+\protected\def\strc_notes_set_location_step#alternative% the insert related one
+ {\begincsname\??notelocation#alternative\endcsname}
+
+\appendtoks
+ \strc_notes_set_variants
+ \strc_notes_set_delayed
+\to \everysynchronizenote
+
+\newskip \s_strc_notes_distance % we need to implement stretch
+\newcount\c_strc_notes_columns
+
+\newskip \s_strc_notes_before
+\newskip \s_strc_notes_inbetween
+\newconditional\c_strc_notes_first_flushed
+
+\appendtoks
+ \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}%
+ \ifx\p_spacebefore\empty
+ \global\s_strc_notes_before\zeropoint
+ \else
+ \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}%
+ \fi
+ \edef\p_spaceinbetween{\rootnoteparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty
+ \global\s_strc_notes_inbetween\zeropoint
+ \else
+ \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}%
+ \fi
+\to \everysynchronizenote
+
+\def\strc_notes_set_distance
+ {\begingroup
+ \restoreglobalbodyfont
+ \setbox\scratchbox\vbox % no reuse as it can mirror
+ {\forgetall
+ \dontcomplain
+ \noteparameter\c!before
+ \placenoterule
+ \strut
+ \noteparameter\c!after}%
+ % also dp now
+ \scratchdimen\dimexpr\htdp\scratchbox-\lineheight\relax
+ \ifgridsnapping
+ \getnoflines\scratchdimen
+ \scratchdimen\noflines\lineheight
+ \fi
+ \expandafter\endgroup\expandafter
+ \s_strc_notes_distance\the\scratchdimen\relax}
+
+\def\strc_notes_set_columns
+ {\c_strc_notes_columns\noteparameter\c!n\relax
+ \ifcase\c_strc_notes_columns
+ \c_strc_notes_columns\plusone
+ \fi}
+
+\def\strc_notes_set_location_page
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]%
+ \global\count\currentnoteinsertionnumber\numexpr(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_columns
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \ifnum\currentnofcolumns=\zerocount
+ \c_strc_notes_columns\plusone
+ \fi
+ \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]%
+ \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_somecolumn#whatcolumn%
+ {\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]%
+ \global\count\currentnoteinsertionnumber\plusthousand
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
+
+\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn}
+\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn }
+
+\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
+ {\settrue\c_strc_notes_delayed
+ \clf_setnotestate{\currentnote}{store}%
+ \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]%
+ \global\count\currentnoteinsertionnumber\zerocount
+ \global\dimen\currentnoteinsertionnumber\maxdimen
+ \global\skip \currentnoteinsertionnumber\zeropoint}
+
+\let\strc_notes_set_location_none\strc_notes_set_location_text
+
+\def\strc_notes_set_properties
+ {\strc_notes_set_columns
+ \strc_notes_set_distance
+ \strc_notes_set_location
+ \strc_notes_set_delayed}
+
+\let\strc_notes_set_position_high\relax
+
+\def\strc_notes_set_position_bottom
+ {\settrue\c_notes_bottom_present}
+
+\appendtoks
+ \strc_notes_set_properties
+\to \everysynchronizenote
+
+%D A fast checker for bottom notes being used:
+
+\newconditional\c_notes_bottom_present
+
+\def\strc_notes_check_if_bottom_present_indeed % in otr !
+ {\ifvoid\currentnoteinsertionnumber\else
+ \strc_notes_set_position
+ \fi}
+
+\def\strc_notes_check_if_bottom_present_step
+ {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi}
+
+\def\strc_notes_check_if_bottom_present
+ {\setfalse\c_notes_bottom_present
+ \strc_notes_process\strc_notes_check_if_bottom_present_step}
+
+% Example of using factor:
+%
+% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0]
+% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle]
+% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
+% \starttext
+% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} }
+% \stoptext
+
+%D The noterule can be a graphic and therefore calling this setup macro at every
+%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that
+%D probably match those of the stretch component. A bit messy:
+
+\permanent\protected\def\placenoterule
+ {\begingroup
+ \currentnoterulealign
+ \currentnoterulecommand
+ \par
+ \endgroup}
+
+\permanent\protected\def\normalnoterule
+ {\ifvmode
+ \dontleavehmode \blackrule
+ [\c!color=\noteparameter\c!rulecolor,
+ \c!width=.2\hsize,
+ \c!height=\noteparameter\c!rulethickness,
+ \c!depth=\zeropoint]%
+ \endgraf
+ \kern\strutdepth
+ \fi}
+
+%D The formatting depends on the width of the table, so we have to set \type {n} to
+%D zero.
+%D
+%D \starttyping
+%D \startbuffer
+%D \bTABLE
+%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR
+%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \startlocalfootnotes[n=0,location={text,none}]
+%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes}
+%D \stoplocalfootnotes
+%D \stoptyping
+
+%D \macros
+%D {footnote}
+%D
+%D A footnote can have a reference as optional argument and therefore its formal
+%D specification looks like:
+%D
+%D \showsetup{footnote}
+%D
+%D This command has one optional command: the reference. By saying \type{[-]} the
+%D number is omitted. The footnote command is not that sensitive to spacing, so it's
+%D quite legal to say:
+%D
+%D \startbuffer
+%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the
+%D ground and not get confused \footnote {Or even crazy.} by all those obscure
+%D \footnote {But fortunately readable.} parameters.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D When setting the \type{conversion} to \type{set 2} we get
+%D something like:
+%D
+%D \bgroup
+%D \startnarrower
+%D \setupfootnotes[conversion=set 1]
+%D \getbuffer
+%D \stopnarrower
+%D \egroup
+%D
+%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes.
+%D The additional macro \type {\footnotetext} and the associated \type {\note} macro
+%D were implemented at request of users on the mailing list and a suggestion by taco
+%D to split of the symbol placement. I decided to merge this functionality with the
+%D existing \type {\note} functionality.
+
+\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used
+\newconditional\c_strc_notes_skip
+
+\permanent\protected\def\setnote [#tag]{\csname#tag\endcsname}
+\permanent\protected\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname}
+
+\permanent\protected\def\handlenoteinsert#tag#id%
+ {\begingroup
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \the\everybeforenoteinsert
+ \insert\currentnoteinsertionnumber\bgroup
+ \the\everyinsidenoteinsert\relax
+ \usesetupsparameter\noteparameter % experimental
+ \useinterlinespaceparameter\noteparameter
+ \doifelse{\noteparameter\c!paragraph}\v!yes
+ {\nointerlineskip
+ \startvboxtohboxseparator
+ \noteparameter\c!inbetween
+ \stopvboxtohboxseparator
+ \startvboxtohbox
+ \handlenoteitself{#tag}{#id}%
+ \stopvboxtohbox}
+ {\handlenoteitself{#tag}{#id}}%
+ \egroup
+ \the\everyafternoteinsert
+ \endgroup}
+
+\permanent\protected\def\betweennoteitself#tag% used ?
+ {\edef\currentnote{#tag}%
+ \doif{\noteparameter\c!paragraph}\v!yes{\noteparameter\c!inbetween}}
+
+\permanent\protected\def\handlenoteitself#tag#id%
+ {\edef\currentnotenumber{#id}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
+ \strc_notes_synchronize
+ \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache
+ % as we can have collected notes (e.g. in tables) we need to recover
+ % \currentdescriptionattribute and \currentdescriptionsynchronize
+ %
+ \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table)
+ %
+ \dontcomplain
+ %begingroup
+ \strc_notes_interaction_check_display
+ \strc_notes_set_reference_attribute_text
+ \strc_constructions_stored_start
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \strc_notes_set_destination_attribute_text
+ \strc_notes_inject_text\relax
+ \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10
+ \strc_constructions_stored_stop
+ %endgroup
+ }
+
+\protected\def\strc_notes_inject_text % hm main?
+ {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}
+
+\let\startpushnote\relax
+\let\stoppushnote \relax
+
+\newsignal\notesignal
+
+\newconditional\processingnote
+\newconditional\postponednote
+
+\newtoks\everybeforenoteinsert
+\newtoks\everyinsidenoteinsert
+\newtoks\everyafternoteinsert
+
+\permanent\protected\def\doifelseinnote
+ {\ifconditional\processingnote
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\appendtoks
+ \enforced\let\flushnotes \relax
+ \enforced\let\postponenotes\relax
+ \forgetall
+ \resetallattributes % new, we don't want color bleed into notes
+ \inheritmaintextcolor % but we do want to obey the textcolor
+\to \everybeforenoteinsert
+
+\def\strc_notes_set_penalties
+ {% stored in insert node
+ \floatingpenalty \currentnotepenalty
+ % used when typesetting
+ \interlinepenalty\plushundred % plain value
+ % used when we need to split in columns
+ \ifnum\noteparameter\c!n>\plusone
+ \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated)
+ \fi}
+
+\appendtoks
+ \strc_notes_set_penalties
+ \forgetall % again
+ \strc_notes_set_bodyfont
+ \redoconvertfont % to undo \undo calls in in headings etc
+ \splittopskip\strutht % not actually needed here
+ \splitmaxdepth\strutdp % not actually needed here
+ %
+ % not:
+ %
+ % \leftmargindistance \noteparameter\c!margindistance
+ % \rightmargindistance\leftmargindistance
+ % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
+ % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
+ % \fi
+ %
+ \pickupattributes
+\to \everyinsidenoteinsert
+
+%D Nasty, the might be more:
+
+\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert
+\appendtoks \strc_itemgroups_pop \to \everyafternoteinsert
+
+% maybe but better use [scope=local] here
+%
+% \appendtoks
+% \setfalse\inhibitmargindata
+% \to \everyinsidenoteinsert
+
+\setupnotes
+ [\c!width=\v!auto]
+
+\permanent\protected\def\setnotehsize
+ {\ifinsidemulticolumns
+ \setnoteparameter\c!width{\makeupwidth}%
+ \else
+ \edef\p_width{\noteparameter\c!width}%
+ \ifx\p_width\v!auto
+ % \ifinsidecolumns
+ \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}%
+ % \else
+ % \setnoteparameter\c!width{\makeupwidth}%
+ % \fi
+ \orelse\ifx\p_width\empty
+ \setnoteparameter\c!width{\hsize}%
+ \fi
+ \fi
+ \hsize\noteparameter\c!width\relax}
+
+\appendtoks
+ % only needed when columns (could be three \set...)
+ \setnotehsize
+ \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+\to \everyinsidenoteinsert
+
+%D Normally footnotes are saved as inserts that are called upon as soon as the
+%D pagebody is constructed. The footnote insertion routine looks just like the
+%D \PLAIN\ \TEX\ one, except that we check for the end note state.
+
+% testcase for split bottom alignment see (a) below
+%
+% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}}
+
+\newconditional\c_strc_notes_first_placed
+
+\permanent\protected\def\placenoteinserts
+ {\setfalse\c_strc_notes_first_placed
+ \strc_notes_process\strc_notes_place_inserts}
+
+\def\strc_notes_place_inserts
+ {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
+ \ifconditional\c_strc_notes_delayed \else
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test
+ \strc_notes_place_inserts_indeed
+ \settrue\c_strc_notes_first_placed
+ \fi
+ \fi}
+
+\def\strc_notes_place_inserts_indeed
+ {\relax
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint
+ \endgraf
+ \ifvmode
+ \whitespace
+ \ifconditional\c_strc_notes_first_placed
+ \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}%
+ \ifx\p_spaceinbetween\empty\else
+ \blank[\p_spaceinbetween]%
+ \fi
+ \else
+ \edef\p_spacebefore{\noteparameter\c!spacebefore}%
+ \ifx\p_spacebefore\empty\else
+ \blank[\p_spacebefore]%
+ \fi
+ \fi
+ \noteparameter\c!before
+ \fi
+ \placenoterule
+ \bgroup
+ \strc_notes_set_bodyfont
+ \setbox\scratchbox\hbox
+ {\strc_notes_flush_inserts}%
+ \page_postprocessors_linenumbers_deepbox\scratchbox
+ \setbox\scratchbox\hbox
+ {\setupcurrentnote
+ [\c!location=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay]%
+ \inheritednoteframed
+ {\ifzeropt\dp\scratchbox % this hack is needed because \vadjust
+ \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement
+ \else % hides the (always) present depth
+ \box\scratchbox
+ \fi}}%
+ \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth
+ \ifvmode
+ \nointerlineskip % else sometimes empty line
+ \fi
+ \box\scratchbox
+ \egroup
+ \endgraf
+ \ifvmode
+ \noteparameter\c!after
+ \fi
+ \fi}
+
+\def\strc_notes_flush_inserts
+ {\ifcase\noteparameter\c!n\relax
+ % should not happen
+ \or
+ \strc_notes_flush_inserts_normal
+ \else
+ \strc_notes_flush_inserts_columns
+ \fi}
+
+\def\strc_notes_flush_inserts_normal
+ {\strc_notes_flush_global
+ \obeydepth} % (a) added , since split footnotes will not align properly
+
+\def\strc_notes_flush_inserts_columns
+ {\begingroup
+ \setnotehsize % probably still not ok for columns
+ \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+ \strc_notes_flush_global
+ \stopsimplecolumns
+ \endgroup}
+
+% idea: tag with attr and then just flush them again
+
+\def\strc_notes_flush_global
+ {\begingroup
+ \useinterlinespaceparameter\noteparameter
+ \doifelse{\noteparameter\c!paragraph}\v!yes
+ {\leftorrightvbox % cf mail from ws to list
+ {\starthboxestohbox
+ \iftrialtypesetting\unvcopy\else\unvbox\fi\currentnoteinsertionnumber
+ \stophboxestohbox}}
+ {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}%
+ \endgroup}
+
+%D Supporting end notes is surprisingly easy. Even better, we can combine this
+%D feature with solving the common \TEX\ problem of disappearing inserts when
+%D they're called for in deeply nested boxes. The general case looks like:
+%D
+%D \starttyping
+%D \postponenotes
+%D \.box{whatever we want with footnotes}
+%D \flushnotes
+%D \stoptyping
+%D
+%D This alternative can be used in headings, captions, tables etc. The latter one
+%D sometimes calls for notes local to the table, which can be realized by saying
+%D
+%D \starttyping
+%D \setlocalfootnotes
+%D some kind of table with local footnotes
+%D \placelocalfootnotes
+%D \stoptyping
+%D
+%D Postponing is accomplished by simply redefining the (local) insert operation. A
+%D not too robust method uses the \type{\insert} primitive when possible. This
+%D method fails in situations where it's not entirely clear in what mode \TEX\ is.
+%D Therefore the auto method can is to be overruled when needed.
+
+\newconditional\postponingnotes
+
+% we need a proper state: normal, postponing, flushing
+
+\permanent\protected\def\postponenotes % will be locally overloaded
+ {\ifcase\insertionmigrationmode
+ \ifconditional\postponingnotes\else
+ \global\settrue\postponingnotes
+ \glet\flushnotes\doflushnotes
+ \clf_postponenotes
+ \fi
+ \fi}
+
+\let\flushnotes\relax
+
+% also \ifcase\insertionmigrationmode here, needs testing:
+
+\permanent\protected\def\startpostponingnotes % experimental, page-mix
+ {\ifconditional\postponingnotes\else
+ \global\settrue\postponingnotes
+ %\glet\flushnotes\doflushnotes
+ \clf_postponenotes
+ \fi}
+
+\permanent\protected\def\stoppostponingnotes % experimental, page-mix
+ {\doflushnotes}
+
+\permanent\protected\def\doflushnotes
+ {\ifconditional\postponingnotes
+ \begingroup
+ \enforced\let\flushnotes \relax
+ \enforced\let\postponenotes\relax
+ \ifconditional\postponednote
+ \ifhmode
+ % needed for tagging ... otherwise we get some weird node free error
+ \signalcharacter
+ \fi
+ \fi
+ \clf_flushpostponednotes% this also resets the states !
+ \global\setfalse\postponednote
+ \global\setfalse\postponingnotes
+ \glet\flushnotes\relax
+ \endgroup
+ \fi}
+
+%D \macros
+%D {startlocalfootnotes,placelocalfootnotes}
+%D
+%D The next two macros can be used in for instance tables, as we'll demonstrate
+%D later on.
+%D
+%D \showsetup{startlocalfootnotes}
+%D \showsetup{placelocalfootnotes}
+
+% todo: compatibility mode: when first arg is assignment or missing, then all
+
+\newtoks\everyplacelocalnotes
+
+\appendtoks
+ \enforced\let\flushnotes \relax
+ \enforced\let\postponenotes\relax
+\to \everyplacelocalnotes
+
+\newconditional\inlocalnotes
+
+\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings)
+ {\def\localnoteslist{#list}%
+ \settrue\inlocalnotes
+ \processcommacommand[\localnoteslist]\strc_notes_local_start_step}
+
+\permanent\protected\def\stoplocalnotes
+ {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step
+ \setfalse\inlocalnotes}
+
+\let\p_strc_notes_continue\empty
+
+\def\strc_notes_local_start_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_save{#tag}%
+ \strc_counters_reset{#tag}%
+ \fi
+ \clf_savenote{#tag}{store}}
+
+\def\strc_notes_local_stop_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_restore{#tag}%
+ \fi
+ \clf_restorenote{#tag}}
+
+\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#settings]%
+ {\doif{\clf_getnotestate{#tag}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}}
+
+\def\strc_notes_local_place_indeed#settings#tag%
+ {\begingroup
+ \edef\currentnote{#tag}% is already set?
+ \the\everyplacelocalnotes
+ % beware, we cannot trust setting \currentnote here
+ \setupcurrentnote[#settings]% later we set height etc for framed
+ \strc_notes_place_local_alternative
+ \strc_notes_set_properties % restore globals (if needed)
+ \endgroup
+ }% TODO: just restore properties \the\everychecknote} % we need to restore the old state
+
+%D These commands can be used like:
+%D
+%D \startbuffer
+%D \startlocalnotes[footnote]
+%D \placetable
+%D {Some Table}
+%D \placeontopofeachother
+%D {\starttable[|l|r|]
+%D \HL
+%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR
+%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR
+%D \HL
+%D \stoptable}
+%D {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]%
+%D \placelocalnotes[footnote]}
+%D \stoplocalnotes
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Because this table placement macro expect box content, and thanks to the grouping
+%D of the local footnotes, we don't need additional braces.
+%D
+%D \getbuffer
+
+%D \macros
+%D {placefootnotes}
+%D
+%D We still have no decent command for placing footnotes somewhere else than at the
+%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can
+%D be placed by using
+%D
+%D \showsetup{placefootnotes}
+
+\permanent\protected\def\placebottomnotes
+ {\strc_notes_process\strc_notes_place_inserts}
+
+\permanent\tolerant\protected\def\placenotes[#list]#spacer[#settings]%
+ {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}}
+
+\def\strc_notes_place_indeed#settings#tag% settings note
+ {\edef\currentnote{#tag}% grouping ?
+ \doifelse{\clf_getnotestate{#tag}}{store}
+ \strc_notes_local_place_indeed
+ \strc_notes_global_place_indeed
+ {#settings}{#tag}}
+
+\def\strc_notes_global_place_indeed#settings#tag%
+ {\begingroup
+ \setupnote[#tag][#settings]%
+ \strc_notes_place_inserts
+ \endgroup
+ \the\everysetupnote} % to be checked .. synchronize
+
+%D Placement
+
+\installcorenamespace{notealternative}
+
+\permanent\protected\def\installnotealternative#alternative#command%
+ {\setvalue{\??notealternative#alternative}{#command}}
+
+\permanent\protected\def\doifnotescollected#tag%
+ {\clf_doifnotecontent{#tag}}
+
+\def\strc_notes_place_local_alternative % will be a setup (wrapper)
+ {\doifnotescollected\currentnote
+ {\endgraf
+ \ifvmode
+ \whitespace
+ \noteparameter\c!before
+ \fi
+ \begingroup
+ \strc_notes_set_bodyfont
+ \csname\??notealternative\noteparameter\c!alternative\endcsname
+ \endgroup
+ \ifvmode
+ \noteparameter\c!after
+ \fi}}
+
+%D A stupid alternative is also provided:
+%D
+%D \starttyping
+%D \setupfootnotes[location=text,alternative=none]
+%D \stoptyping
+
+% setups ?
+
+\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}}
+
+\installnotealternative \v!none
+ {\flushlocalnotes\currentnote}
+
+\installnotealternative \empty
+ {\flushlocalnotes\currentnote}
+
+\installnotealternative \v!grid % test if n > 0
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \snaptogrid\hbox
+ {\inheritednoteframed
+ {\flushlocalnotes\currentnote}}%
+ \endgroup}
+
+\installnotealternative \v!fixed % test if n > 0
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \inheritednoteframed
+ {\flushlocalnotes\currentnote}%
+ \endgroup}
+
+\installnotealternative \v!columns % redundant
+ {\begingroup
+ \setupcurrentnote[\c!location=]%
+ \inheritednoteframed
+ {\edef\currentnotewidth{\noteparameter\c!width}%
+ \doifelsedimension\currentnotewidth\donothing
+ {\edef\currentnotewidth{\the\hsize}}%
+ \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]%
+ \flushlocalnotes\currentnote
+ \stopsimplecolumns}%
+ \endgroup}
+
+% 0:page 1:firstcolumn 2:lastcolumn
+
+\newconstant\c_strc_notes_page_location
+
+\protected\def\strc_notes_check_locations
+ {\edef\p_strc_notes_location{\rootnoteparameter\c!location}%
+ \c_strc_notes_page_location
+ \ifx\p_strc_notes_location\v!firstcolumn\plusone \else
+ \ifx\p_strc_notes_location\v!lastcolumn \plustwo \else
+ \zerocount\fi\fi}
+
+\appendtoks
+ \strc_notes_check_locations
+\to \everysynchronizenote
+
+% still semi public (but will change)
+
+\newif\ifnotespresent
+
+\permanent\protected\def\checknotepresence
+ {\notespresentfalse
+ \strc_notes_process\strc_notes_check_presence}
+
+\def\strc_notes_check_presence
+ {\ifdim\ht\currentnoteinsertionnumber>\zeropoint
+ \notespresenttrue
+ \fi}
+
+%D \macros
+%D {fakenotes}
+
+ % used in page-mul
+
+ \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
+
+ \protected\def\fakenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalclevernoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ \protected\def\fakepagenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalpagenoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ % used in page-not but not yet ok
+
+ \newdimen\totalnoteheight
+
+ \protected\def\additionaltotalnoteheight#insert% temp hacks anyway
+ {\dimexpr
+ \ifdim\ht#insert>\zeropoint
+ \ifcase\count#insert %
+ \zeropoint
+ \else % todo: divide by count
+ \ht#insert+\skip#insert% hm, no stretch but a dimen anyway
+ \fi
+ \else
+ \zeropoint
+ \fi
+ \relax}
+
+ \def\docalculatetotalnoteheight
+ {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
+
+ \def\docalculatetotalclevernoteheight
+ {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
+
+ \def\docalculatetotalpagenoteheight
+ {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}}
+
+ \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
+ \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
+ \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight}
+
+%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing
+%D footnotes? The solution turned out to be rather simple:
+%D
+%D \starttyping
+%D \everypar {...\flushnotes...}
+%D \neverypar {...\postponenotes}
+%D \stoptyping
+%D
+%D We can use \type {\neverypar} because in most commands sensitive to footnote
+%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact,
+%D this footnote implementation is the first to use this scheme.
+
+%D This is a nasty and new secondary footnote flusher. It can be hooked into \type
+%D {\everypar} like:
+%D
+%D \starttyping
+%D \appendtoks \synchronizenotes \to \everypar
+%D \stoptyping
+
+\let\synchronizenotes\relax
+
+%D When typesetting footnotes, we have to return to the footnote specific bodyfont
+%D size, which is in most cases derived from the global document bodyfont size. In
+%D the previous macros we already used a footnote specific font setting macro.
+
+\def\strc_notes_set_bodyfont
+ {\let\strc_notes_set_bodyfont\relax
+ \restoreglobalbodyfont
+ \usebodyfontparameter\noteparameter
+ \usealignparameter\noteparameter}
+
+%D The footnote mechanism defaults to a traditional one column way of showing them.
+%D By default we precede them by a small line.
+
+% end notes in the margin:
+%
+% \setuptexttexts
+% [margin]
+% [] [{\directsetup{notabene}}]
+%
+% \startsetups notabene
+% \vbox to \textheight \bgroup
+% \setupalign[tolerant]
+% \topskipcorrection
+% \placenotes[endnote][before=,after=]
+% \vfilll
+% \egroup
+% \stopsetups
+
+\definenote [\v!footnote]
+\definenote [\v!endnote ] [\c!location=\v!none] % else no break
+
+%D Compatibility macros:
+
+\permanent\protected\def\setupfootnotedefinition{\setupnotation [\v!footnote]}
+\permanent\protected\def\setupfootnotes {\setupnote [\v!footnote]}
+\permanent \def\footnotetext {\setnotetext [\v!footnote]}
+\permanent\protected\def\placefootnotes {\dodoubleempty\strc_notes_place_footnotes [\v!footnote]}
+\permanent\protected\def\placelocalfootnotes {\dodoubleempty\strc_notes_place_local_footnotes[\v!footnote]}
+\permanent\protected\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote
+\permanent\protected\def\stoplocalfootnotes {\stoplocalnotes }
+
+\def\strc_notes_place_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placenotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placenotes[#list][\c!height=\textheight]%
+ \fi}
+
+\def\strc_notes_place_local_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placelocalnotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placelocalnotes[#list][\c!height=\textheight]%
+ \fi}
+
+%D Goodies:
+%D
+%D \starttyping
+%D \dorecurse {100} {
+%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
+%D }
+%D \stoptyping
+
+\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}}
+
+\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage
+
+%D New trickery:
+
+%D \macros
+%D {note}
+%D
+%D Refering to a note is accomplished by the rather short command:
+%D
+%D \showsetup{note}
+%D
+%D This command is implemented rather straightforward as:
+
+\installcorenamespace{notesymbol}
+
+\let\lastnotesymbol\relax % todo: per class
+
+\permanent\tolerant\protected\def\notesymbol[#tag]#spacer[#reference]%
+ {\ifnotesenabled
+ \dontleavehmode
+ \begingroup
+ \edef\currentnote{#tag}%
+ \usenotestyleandcolor\c!textstyle\c!textcolor
+ \iftok{#reference}\emptytoks
+ \noteparameter\c!textcommand\lastnotesymbol % check if command double
+ \else
+ \unskip
+ \noteparameter\c!textcommand{\in[#reference]}% command here?
+ \fi
+ \endgroup
+ \fi}
+
+\permanent\tolerant\protected\def\note[#tag]#spacer[#reference]%
+ {\iftok{#reference}\emptytoks
+ \notesymbol[\v!footnote][#tag]%
+ \else
+ \notesymbol[#tag][#reference]%
+ \fi}
+
+% will be redone if needed
+%
+% \def\ownnotesymbol#1% #1 gets number passed
+% {\executeifdefined{\??notesymbol\currentnote}\empty}
+%
+% \protected\def\setnotesymbol[#1]#2#3%
+% {\prewordbreak % prevent lookback
+% \setgvalue{\??notesymbol#1}{#3}
+% \strc_notes_inject_symbol}
+%
+% \protected\def\ownnote[#1]#2#3#4%
+% {\setnotesymbol[#1]{#2}{#3}%
+% \setnotetext [#1]{#4}}
+%
+% \defineconversion
+% [ownnote]
+% [\ownnotesymbol]
+
+% tricky:
+%
+% \enabletrackers[nodes.areas]
+% \enabletrackers[nodes.references]
+% \enabletrackers[nodes.destinations]
+%
+% \setupnotes[interaction=all,rule=no]
+% \setupinteraction[state=start,focus=standard]
+%
+% \starttext
+% \goto{\input tufte\relax}[page(2)] \par
+% \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par
+% \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par
+% % \completecontent
+% % \chapter{Chapter}
+% % \dorecurse{5}{\input knuth}
+% a\footnote{\input tufte\par\input ward\relax}
+% \stoptext
+
+%D Bonus:
+
+\appendtoks
+ \setsystemmode\currentnote
+\to \everysynchronizenote
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-pag.mkiv b/tex/context/base/mkiv/strc-pag.mkiv
index 01361e2c5..909c418f9 100644
--- a/tex/context/base/mkiv/strc-pag.mkiv
+++ b/tex/context/base/mkiv/strc-pag.mkiv
@@ -21,14 +21,14 @@
% Allocation:
-\countdef\realpageno \zerocount \realpageno \plusone
-\countdef\userpageno \plusone \userpageno \plusone
-\countdef\subpageno \plustwo \subpageno \plusone % was \zerocount but that doesn't work well with bytext
-\countdef\arrangeno \plusthree \arrangeno \zerocount % !
-\countdef\pagenoshift\plusfour \pagenoshift\zerocount % !
-\countdef\lastpageno \plusfive \lastpageno \zerocount % !
+\ifdefined\realpageno \else \countdef\realpageno \zerocount \fi \realpageno \plusone
+\ifdefined\userpageno \else \countdef\userpageno \plusone \fi \userpageno \plusone
+\ifdefined\subpageno \else \countdef\subpageno \plustwo \fi \subpageno \plusone % was \zerocount but that doesn't work well with bytext
+\ifdefined\arrangeno \else \countdef\arrangeno \plusthree \fi \arrangeno \zerocount % !
+\ifdefined\pagenoshift \else \countdef\pagenoshift\plusfour \fi \pagenoshift\zerocount % !
+\ifdefined\lastpageno \else \countdef\lastpageno \plusfive \fi \lastpageno \zerocount % !
-\let\pageno\userpageno
+\ifdefined\pageno \else \let\pageno\userpageno \fi
\def\realfolio{\the\realpageno}
\def\userfolio{\the\userpageno}
@@ -268,8 +268,8 @@
% States:
-\newif\ifdoublesided \newconditional\layoutisdoublesided
-\newif\ifsinglesided \newconditional\layoutissinglesided
+\newconditional\layoutisdoublesided % already defined: \newif\ifdoublesided
+\newconditional\layoutissinglesided % already defined: \newif\ifsinglesided
% Realpage and subpage numbers:
@@ -316,7 +316,8 @@
\doublesidedfalse \setfalse\layoutissinglesided
\resetsystemmode\v!singlesided
\resetsystemmode\v!doublesided
- \processallactionsinset[\directpagenumberingparameter\c!alternative]
+ \processallactionsinset
+ [\directpagenumberingparameter\c!alternative]%
[ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided,
\v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]%
\the\everysidedswitch
diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi
index d68ecb805..3bf339638 100644
--- a/tex/context/base/mkiv/strc-ref.mkvi
+++ b/tex/context/base/mkiv/strc-ref.mkvi
@@ -1006,8 +1006,8 @@
\unexpanded\def\strc_references_about[#label]%
{\dontleavehmode
\begingroup
- \let\crlf\space
- \let\\\space
+ \enforced\let\crlf\space
+ \enforced\let\\\space
\postponenotes % might go
\referencingparameter\c!left
\doifelsereferencefound{#label}
diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv
index e2fede024..1e632eebc 100644
--- a/tex/context/base/mkiv/strc-reg.mkiv
+++ b/tex/context/base/mkiv/strc-reg.mkiv
@@ -48,7 +48,7 @@
\let\strc_registers_setup_saved\setupregister
-\unexpanded\def\setupregister % maybe we should drop the plural form
+\unexpanded\overloaded\def\setupregister % maybe we should drop the plural form
{\dotripleempty\strc_registers_setup}
\def\strc_registers_setup[#1][#2][#3]%
@@ -618,7 +618,7 @@
\edef\currentregister{\firstinset{#1}}%
\the\everyplaceregister
\ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone
- \startmixedcolumns[\currentregister]
+ \startmixedcolumns[\currentregister]%
\strc_registers_place_indeed{#1}%
\stopmixedcolumns
\else
diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv
index 2b344bbfb..359bd6aec 100644
--- a/tex/context/base/mkiv/strc-ren.mkiv
+++ b/tex/context/base/mkiv/strc-ren.mkiv
@@ -187,7 +187,7 @@
\ifx\p_strut\v!no
\setnostrut
\fi
- \let\\\strc_rendering_shortcut_backslash}
+ \enforced\let\\\strc_rendering_shortcut_backslash}
\unexpanded\def\strc_rendering_shortcut_backslash
{\crlf
@@ -745,8 +745,8 @@
\vbox {
\headsetupspacing
\veryraggedcenter
- \let\\\endgraf
- \let\crlf\endgraf
+ \enforced\let\\\endgraf
+ \enforced\let\crlf\endgraf
\ifconditional\headshownumber
\strut
\headnumbercontent
diff --git a/tex/context/base/mkiv/strc-sbe.mkxl b/tex/context/base/mkiv/strc-sbe.mkxl
new file mode 100644
index 000000000..1b903cec7
--- /dev/null
+++ b/tex/context/base/mkiv/strc-sbe.mkxl
@@ -0,0 +1,139 @@
+%D \module
+%D [ file=strc-sbe,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Section Block Environments,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Section Block Environments}
+
+\unprotect
+
+% \def\ChapterEntry#1#2#3%
+% {chapter : \hbox to \hsize{\strut\bf#2\hss#3}\endgraf\placelist[section]}
+%
+% \startfrontmatter % optional
+% \placelist[chapter][alternative=command,command=\ChapterEntry,criterium=text] \page
+% \stopfrontmatter % optional
+%
+% \startbodymatter % optional
+% \chapter{first} \section{one} test \section{two} test \page
+% \chapter{second} \section{alpha} test \section{beta} test \page
+% \stopbodymatter % optional
+
+\installcorenamespace{sectionblock}
+
+\installcommandhandler \??sectionblock {sectionblock} \??sectionblock
+
+\setupsectionblock
+ [\c!number=\v!yes,
+ \c!page=\v!right] % otherwise marks are reset too soon
+
+\newtoks\everybeforesectionblock
+\newtoks\everyaftersectionblock
+
+\let\strc_sectionblock_define_normal\definesectionblock
+
+\permanent\overloaded\tolerant\protected\def\definesectionblock[#1]#*[#2]#*[#3]% singular plural settings
+ {\strc_sectionblock_define_normal[#1][#3]%
+ %\expandafter\newif\csname if#2\endcsname % obsolete
+ \strc_sectionblock_set_environment{#1}\empty
+ \setuvalue{\e!start#2}{\startsectionblock[#1]}%
+ \setuvalue{\e!stop #2}{\stopsectionblock}}
+
+\ifdefined \resetallstructuremarks \else
+ \let\resetallstructuremarks\relax
+\fi
+
+\def\strc_sectionblock_handle_page
+ {\edef\p_strc_sectionblock_page{\sectionblockparameter\c!page}%
+ \ifx\p_strc_sectionblock_page\empty \else
+ \page[\p_strc_sectionblock_page]%
+ \fi}
+
+\appendtoks
+ \strc_sectionblock_handle_page
+ \resetallstructuremarks
+ \strc_sectionblock_get_environment\currentsectionblock
+ \sectionblockparameter\c!before % don't move
+ \dostarttagged\t!division\currentsectionblock % no parents
+\to \everybeforesectionblock
+
+\appendtoks
+ \sectionblockparameter\c!after % don't move
+ \strc_sectionblock_handle_page
+ \dostoptagged
+ \resetallstructuremarks
+\to \everyaftersectionblock
+
+\permanent\tolerant\protected\def\setsectionblock[#1]#*[#2]% used to set the default
+ {\edef\currentsectionblock{#1}% from now on we assume a value
+ \setupcurrentsectionblock[#2]%
+ \clf_setsectionblock{#1}
+ bookmark {\sectionblockparameter\c!bookmark}%
+ \relax}
+
+\let\currentsectionblock\empty % was \s!unknown
+
+\permanent\tolerant\protected\def\startsectionblock[#1]#*[#2]%
+ {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push)
+ \begingroup
+ \edef\currentsectionblock{#1}% from now on we assume a value
+ \setupcurrentsectionblock[#2]%
+ \clf_pushsectionblock{#1}
+ bookmark {\sectionblockparameter\c!bookmark}%
+ \relax
+ %\csname #1true\endcsname % obsolete
+ \setsystemmode\currentsectionblock
+ \the\everybeforesectionblock\relax
+ \showmessage\m!structures1\currentsectionblock}
+
+\permanent\protected\def\stopsectionblock
+ {\showmessage\m!structures2\currentsectionblock
+ \the\everyaftersectionblock\relax
+ \clf_popsectionblock
+ \endgroup}
+
+%D \starttyping
+%D \startsectionblockenvironment[frontpart]
+%D \setupnumber[userpage][numberconversion=romannumerals,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \startsectionblockenvironment[bodypart]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \startsectionblockenvironment[backpart]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
+%D \stopsectionblockenvironment
+%D
+%D \starttext
+%D \startfrontmatter \chapter{test} \stopfrontmatter
+%D \startbodymatter \chapter{test} \stopbodymatter
+%D \startappendices \chapter{test} \stopappendices
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{sectionblockenvironment}
+
+\protected\def\strc_sectionblock_set_environment#1#2%
+ {\setvalue{\??sectionblockenvironment#1}{#2}}
+
+\protected\def\strc_sectionblock_get_environment#1%
+ {\csname\??sectionblockenvironment#1\endcsname}
+
+\protected\setvalue{\e!start\v!sectionblockenvironment}%
+ {\dosingleargument\strc_sectionblock_environment_start}
+
+\letvalue{\e!stop\v!sectionblockenvironment}\relax
+
+\def\strc_sectionblock_environment_start[#1]% evt \pushendofline \popendofline
+ {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv
index 2a2384656..fb21254f2 100644
--- a/tex/context/base/mkiv/strc-sec.mkiv
+++ b/tex/context/base/mkiv/strc-sec.mkiv
@@ -1044,7 +1044,7 @@
\def\strc_sectioning_delayed_flush
{\ifvoid\b_sectioning_delayed\else
- \smashboxed\b_sectioning_delayed
+ \smashedbox\b_sectioning_delayed
\fi}
\unexpanded\def\strc_rendering_place_head_section % see hidden below
diff --git a/tex/context/base/mkiv/strc-sec.mkxl b/tex/context/base/mkiv/strc-sec.mkxl
new file mode 100644
index 000000000..51d1f6019
--- /dev/null
+++ b/tex/context/base/mkiv/strc-sec.mkxl
@@ -0,0 +1,1345 @@
+%D \module
+%D [ file=strc-sec,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Sectioning,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D In retrospect I should have gone futher and move more to the
+%D \LUA\ end but here we are now. Maybe some day.
+
+\writestatus{loading}{ConTeXt Structure Macros / Sectioning}
+
+\unprotect
+
+\startcontextdefinitioncode
+
+\installcorenamespace{structure}
+
+\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters
+
+\setupstructure % not a user command so we might need to change the name
+ [\c!number=,
+ \c!level=,
+ \c!name=,
+ \c!title=,
+ \c!bookmark=,
+ \c!marking=,
+ \c!list=,
+ \c!label=,
+ \c!coupling=,
+ \c!ownnumber=,
+ % \c!interaction=\v!list,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionconversionset=\s!default,
+ \c!sectionstopper=,
+ \c!sectionstarter=,
+ \c!sectionsegments=,
+ \c!sectionresetset=,
+ \c!reference=,
+ \c!backreference=,
+ \c!expansion=\v!no,
+ \c!xmlsetup=,
+ \s!catcodes=,
+ \c!saveinlist=\v!yes]
+
+% maybe flags for list, bm, mark
+
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\let\currentstructurereferenceprefix\empty
+
+\installglobalmacrostack\currentstructurereferenceprefix
+
+\def\strc_sectioning_set_reference_prefix
+ {\ifx\currentstructurereferenceprefix\empty
+ % nothing
+ \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes
+ \global\advance\prefixcounter \plusone % temp here
+ \setupglobalreferenceprefix[\the\prefixcounter]%
+ \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop
+ \setupglobalreferenceprefix[]%
+ \else
+ \setupglobalreferenceprefix[\currentstructurereferenceprefix]%
+ \fi
+ \glet\currentstructurereferenceprefix\referenceprefix}
+
+% why xdef ?
+
+\setupstructure
+ [\c!label={\headparameter{\currentsectionblock\c!label}},
+ \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed
+ \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi,
+ \c!level=\currentheadlevel,
+ \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
+ \c!expansion=\headparameter\c!expansion,
+ \c!xmlsetup=\headparameter\c!xmlsetup,
+ \s!catcodes=\headparameter\s!catcodes,
+ \c!sectionresetset=\headparameter\c!sectionresetset,
+ \c!sectionseparatorset=\headparameter\c!sectionseparatorset,
+ \c!sectionconversionset=\headparameter\c!sectionconversionset,
+ \c!sectionconversion=\headparameter\c!conversion, % just for compatibility
+ \c!sectionstarter=\headparameter\c!sectionstarter,
+ \c!sectionstopper=\headparameter\c!sectionstopper,
+ \c!sectionset=\headparameter\c!sectionset,
+ \c!sectionsegments=\headparameter\c!sectionsegments,
+ \c!reference=\headparameter\c!reference,
+ \c!referenceprefix=\headparameter\c!referenceprefix,
+ \c!criterium=\headparameter\c!criterium]
+
+% see lists/neat-001.tex for usage of:
+
+\permanent\def\namedstructureheadlocation#1% expandable, maybe [#1]
+ {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname}
+
+% The next directive only makes sense when we have sort of garanteed outcome (math is not so
+% nice for instance).
+%
+% \enabledirectives[references.bookmarks.preroll]
+
+\newconditional\c_strc_bookmarks_preroll
+
+\installtexdirective
+ {references.bookmarks.preroll}
+ {\settrue \c_strc_bookmarks_preroll}
+ {\setfalse\c_strc_bookmarks_preroll}
+
+\def\strc_sectioning_autobookmark#1%
+ {\begingroup
+ % \settrialtypesetting
+ \the\everypreroll
+ \nodestostring\tempstring{#1}%
+ \glet\currentstructurebookmark\tempstring
+ \endgroup}
+
+% zeros:
+%
+% \setuphead[subsection][criterium=all]
+%
+% \dorecurse{3} {
+% \chapter{Blabla} \subsection{bla 1 1} \subsection{bla 1 2}
+% \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2}
+% }
+
+\protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported)
+ {\begingroup
+ \setupstructure[\c!name={#1},#2]%
+ \xdef\currentstructurename {\structureparameter\c!name}%
+ \xdef\currentstructurecoupling {\structureparameter\c!coupling}%
+ \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number
+ \xdef\currentstructurelevel {\structureparameter\c!level}%
+ \edef\currentstructureexpansion {\structureparameter\c!expansion}%
+ \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}%
+ \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}%
+ \xdef\currentstructurelabel {\structureparameter\c!label}%
+ \xdef\currentstructurereference {\structureparameter\c!reference}%
+ \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}%
+ \xdef\currentstructurebackreference {\structureparameter\c!backreference}%
+ \xdef\currentstructureshownumber {\structureparameter\c!number}%
+ \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}%
+ \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
+ \xdef\currentstructureplaceholder {\structureparameter\c!placeholder}%
+ \ifx\currentstructureexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \xmlstopraw
+ \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark\currentstructuretitle
+ \fi \fi \fi
+ \ifx\currentstructurelist\empty
+ \glet\currentstructurelist\currentstructuretitle
+ \fi
+ \glet\currentstructurecoding\s!xml
+ \else
+ \ifx\currentstructureexpansion\v!yes
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark\currentstructuretitle
+ \fi \fi \fi
+ \else
+ \xdef\currentstructuretitle {\detokenizedstructureparameter\c!title}%
+ \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}%
+ \xdef\currentstructurelist {\detokenizedstructureparameter\c!list}%
+ \iflocation \ifx\currentstructurebookmark\empty
+ \ifconditional\c_strc_bookmarks_preroll
+ \strc_sectioning_autobookmark{\structureparameter\c!title}%
+ \else
+ \begingroup
+ \simplifycommands
+ \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}%
+ \endgroup
+ \fi
+ \fi \fi
+ \fi
+ \ifx\currentstructurelist\empty
+ \glet\currentstructurelist\currentstructuretitle
+ \fi
+ \glet\currentstructurecoding\s!tex
+ \fi
+ \setnextinternalreference
+ \storeinternalreference\currentstructurename{\the\locationcount}%
+ \strc_sectioning_set_reference_prefix
+ \clf_setsectionentry
+ references {
+ internal \locationcount
+ % block {\currentsectionblock}
+ prefix {\currentstructurereferenceprefix}
+ reference {\currentstructurereference}
+ backreference {\currentstructurebackreference}
+ }
+ directives {
+ resetset {\structureparameter\c!sectionresetset}
+ }
+ metadata {
+ kind {section}
+ name {\currentstructurename}
+ catcodes \ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space
+ coding {\currentstructurecoding}
+ \ifx\currentstructurecoding\s!xml
+ xmlroot {\xmldocument}
+ \fi
+ \ifx\currentstructurexmlsetup\empty \else
+ xmlsetup {\currentstructurexmlsetup}
+ \fi
+ \ifx\currentstructuresaveinlist\v!no
+ nolist \space true\space
+ \fi
+ \ifx\currentstructureincrementnumber\v!yes
+ increment {\currentstructureincrementnumber}
+ \fi
+ }
+ titledata {
+ label {\detokenize\expandafter{\currentstructurelabel}}
+ title {\detokenize\expandafter{\currentstructuretitle}}
+ \ifx\currentstructurebookmark\currentstructuretitle \else
+ bookmark {\detokenize\expandafter{\currentstructurebookmark}}
+ \fi
+ \ifx\currentstructuremarking\currentstructuretitle \else
+ marking {\detokenize\expandafter{\currentstructuremarking}}
+ \fi
+ \ifx\currentstructuresaveinlist\v!no \else
+ \ifx\currentstructurelist\currentstructuretitle \else
+ list {\detokenize\expandafter{\currentstructurelist}}
+ \fi
+ \fi
+ }
+ numberdata {
+ % block {\currentsectionblock}
+ \ifx\currentstructureshownumber\v!no
+ hidenumber \space true\space % space needed for parser
+ \fi
+ separatorset {\structureparameter\c!sectionseparatorset}
+ conversionset {\structureparameter\c!sectionconversionset}
+ conversion {\structureparameter\c!sectionconversion}
+ starter {\structureparameter\c!sectionstarter}
+ stopper {\structureparameter\c!sectionstopper}
+ set {\structureparameter\c!sectionset}
+ segments {\structureparameter\c!sectionsegments}
+ ownnumber {\currentstructureownnumber}
+ language {\currentlanguage}% for the moment, needed for bookmarks conversion
+ criterium {\structureparameter\c!criterium}
+ }
+ userdata {\detokenize{#3}}% will be converted to table at the lua end
+ \relax
+ \xdef\currentstructurelistnumber{\clf_currentsectiontolist}%
+ % \currentstructuresynchronize has to be called someplace, since it introduces a node
+ \setstructuresynchronization\currentstructurelistnumber
+ \endgroup}
+
+\let\currentsectioncountervalue \!!zerocount % redefined later
+\let\previoussectioncountervalue\!!zerocount % redefined later
+
+% We can access the (stored) data with the following macros.
+%
+% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}}
+% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2}
+%
+% \setuphead[chapter][command=\MyHeadCommand]
+% \setuplist[chapter][alternative=command,command=\MyListCommand]
+%
+% \starttext
+% \setupheadertexts[chapter]
+% \setupinteraction[state=start]
+% \placebookmarks[chapter]
+% \placelist[chapter]
+% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps]
+% \stopchapter
+% \stoptext
+
+% todo: #1 => "#1" ... adapt lua code for name and number
+
+\permanent\def\structurenumber {\clf_structurenumber}
+\permanent\def\structuretitle {\clf_structuretitle}
+\permanent\def\structurevariable #1{\clf_structurevariable {#1}}
+\permanent\def\structureuservariable #1{\clf_structureuservariable {#1}}
+\permanent\def\structurecatcodedget #1{\clf_structurecatcodedget {#1}} % bad name
+\permanent\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name
+\permanent\def\structureautocatcodedget #1#2{\clf_structureautocatcodedget {#1}{#2}}
+\permanent\def\namedstructurevariable #1#2{\clf_namedstructurevariable {#1}{#2}}
+\permanent\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}}
+
+% compatibility issue:
+%
+% \def\setfullsectionnumber #1{}
+% \def\preparefullnumber #1{}
+% \def\fullsectionnumber {1--1--1}
+% \def\makesectionnumber [#1]{}
+% \def\makesectionformat {}
+% \def\sectionformat {1--1-1-1-1-1-1}
+% \def\composedsectionnumber{}
+% \def\@@kolist{}
+
+% \setuphead[section] [separator=\separatorlist{?,!,*}]
+% \setuphead[subsection][separator=\separatorlist{??,!!,**}]
+%
+% \let\spr\separatorlist % this will enable this feature
+%
+% \setuphead[section] [separator={?,!,*}]
+% \setuphead[subsection][separator={??,!!,**}]
+%
+% \setupheads[separator={A,B,C,D,E,F}]
+% \chapter{test}
+% \section{test} \subsection{test} \subsection{test}
+% \section{test} \subsection{test} \subsection{test}
+
+% lua interface / names and interface might change
+
+% \newconditional\c_strc_rendering_continuous % not used (mkii ?)
+
+\permanent\def\setstructurelevel #1#2{\clf_setstructurelevel {#1}{#2}} % name, level|parent
+\permanent\def\getstructurelevel #1{\clf_getstructurelevel {#1}} % name
+\permanent\def\setstructurenumber #1#2{\clf_setstructurenumber #1{#2}} % level, number (+/-)
+\permanent\def\getstructurenumber #1{\clf_getstructurenumber \numexpr#1\relax} % level
+\permanent\def\getsomestructurenumber #1#2{\clf_getsomestructurenumber #1{#2}} % level, what
+\permanent\def\getfullstructurenumber #1{\clf_getfullstructurenumber \numexpr#1\relax} % level
+\permanent\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}} % level, what
+\permanent\def\getspecificstructuretitle #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}}
+
+% structure heads (like \startchapter)
+
+% \c!deeptextcommand, \c!deepnumbercommand: undefined !
+% \c!before \c!after \c!distance
+% \c!page \c!header \c!text \c!footer=,
+% \c!numbercommand \c!textcommand \c!ownnumber \c!number
+% \c!file \c!grid \c!margintext
+% \c!expansion \c!xmlsetup \s!catcode
+
+\installcorenamespace{head}
+\installcorenamespace{headlevel}
+\installcorenamespace{headincrement}
+\installcorenamespace{headplace}
+\installcorenamespace{headmarkyes}
+\installcorenamespace{headmarknop}
+
+\installcommandhandler \??head {head} \??head
+
+\installmacrostack\currenthead
+\installmacrostack\currentheadparent
+
+\setuphead [%
+ %\c!after=,
+ %\c!align=,
+ %\c!aligntitle=,
+ \c!alternative=\v!normal,
+ %\c!before=,
+ %\c!color=,
+ %\c!command=,
+ \c!continue=\v!yes,
+ %\c!coupling=,
+ %\c!deepnumbercommand=,
+ %\c!deeptextcommand=,
+ %\c!default=,
+ \c!distance=\zeropoint,
+ \c!textdistance=\zeropoint,
+ \c!textwidth=\zeropoint, % signal too
+ \c!numberwidth=\zeropoint, % signal too
+ \c!width=\zeropoint, % signal too
+ \c!expansion=\v!no,
+ %\c!file=,
+ %\c!footer=,
+ %\c!grid=,
+ \c!hang=\v!none,
+ %\c!header=,
+ \c!incrementnumber=\v!yes,
+ \c!indentnext=\v!no,
+ %\c!label=,
+ %\c!limittext=\languageparameter\c!limittext,
+ \c!margin=\zeropoint,
+ %\c!margintext=,
+ \c!number=\v!yes,
+ \c!numbercolor=\headparameter\c!color,
+ \c!textcolor=\headparameter\c!color,
+ \c!numberstyle=\headparameter\c!style,
+ \c!textstyle=\headparameter\c!style,
+ %\c!numbercommand=,
+ %\c!textcommand=,
+ \c!ownnumber=\v!no,
+ %\c!page=,
+ \c!placehead=\v!yes,
+ \c!sectionconversionset=\s!default,
+ \c!sectionnumber=\v!yes,
+ %\c!sectionsegments=,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionset=\v!all,
+ \c!interlinespace=,
+ %\c!sectionstopper=,
+ %\c!sectionstarter=,
+ %\c!strut=,
+ %\c!style=,
+ %\c!text=,
+ %\c!tolerance=,
+ %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace
+ %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace
+ %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace
+ ]
+
+\let\setupheads\setuphead % will go
+
+\appendtoks
+ \ifx\currentheadparent\empty
+ \edef\currentheaddefault{\headparameter\c!default}%
+ \edef\currentheadsection{\headparameter\c!section}%
+ \ifx\currenthead\currentheaddefault
+ \let\currentheadparent\currentheadsection
+ \orelse\ifx\currentheaddefault\empty
+ \let\currentheadparent\currentheadsection
+ \else
+ \let\currentheadparent\currentheaddefault
+ \fi
+ \normalexpanded {%
+ \setheadparameter{\c!label}{\currenthead}%
+ \setheadparameter{\c!coupling}{\currenthead}%
+ \setheadparameter{\s!parent}{\??head\currentheadparent}%
+ \definemarking[\currenthead] [\currentheadsection]%
+ \definemarking[\currenthead\v!number][\currentheadsection]%
+ \setupmarking [\currenthead] [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]%
+ \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]%
+ }%
+ \doifelselist\currenthead\donothing
+ {\definelist[\currenthead][\c!prefix=\v!no]}%
+ % we can't do this now for backward compatibility reasons
+ % \doifelselist\currenthead\donothing
+ % {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}%
+ \else
+ \normalexpanded {%
+ \setheadparameter{\c!label}{\currenthead}%
+ \setheadparameter{\c!coupling}{\currentheadparent}%
+ \definemarking[\currenthead] [\currentheadparent]%
+ \definemarking[\currenthead\v!number][\currentheadparent\c!number]%
+ }%
+ \doifelselist\currenthead\donothing
+ {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}%
+ \fi
+ \presetlabeltext[\currenthead=]%
+ \the\everysetuphead
+\to \everydefinehead
+
+\newtoks\everyredefinehead
+
+\appendtoks
+ \the\everyredefinehead
+\to \everydefinehead
+
+\appendtoks
+ \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}%
+\to \everyredefinehead
+
+\appendtoks
+ % beware, this is a global register
+ \begingroup
+ \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}%
+ \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}%
+ \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}%
+ \clf_registersection {\currenthead} {
+ coupling {\currentsectionheadcoupling}
+ section {\currentsectionheadsection}
+ level \space \currentsectionlevel \space % space needed for parser
+ parent {\currentheadparent}
+ }%
+ \endgroup
+\to \everyredefinehead
+
+\appendtoks
+ \instance\setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}%
+ \instance\setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}%
+\to \everydefinehead
+
+% so \subject as well as \section will need two commands when ownnumber
+% is used (one can disable it anyway for subject) .. this is not downward
+% compatible but better
+
+\appendtoks
+ \ifx\currenthead\empty \else
+ \doifelse{\headparameter\c!ownnumber}\v!yes
+ {\instance\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}}
+ {\instance\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}%
+ \fi
+\to \everysetuphead
+
+\permanent\protected\def\doredefinehead#1#2% called at lua end
+ {\push_macro_currenthead
+ \push_macro_currentheadparent
+ \edef\currenthead{#1}%
+ \edef\currentheadparent{#2}%
+ \the\everyredefinehead\relax
+ \pop_macro_currentheadparent
+ \pop_macro_currenthead}
+
+\let\currentnamedsection\empty
+
+\installmacrostack\currentnamedsection
+
+% todo: add grouping but where: before/after trickery .. probably inside because one can always add
+% grouping to the before/after settings
+
+\permanent\protected\def\startnamedsection
+ {\dotripleempty\strc_sectioning_start_named_section}
+
+\permanent\protected\def\stopnamedsection
+ {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}}
+
+% structure sections (the parents of chapter etc)
+
+\let\firstsectionname\empty
+\let\lastsectionname \empty
+
+\let\resetallstructuremarks \relax
+\let\resetcurrentstructuremarks \relax
+\let\resetcurrentstructuremarkswithpage\relax
+
+\def\resetallstructuremarks {\resetmarking[\firstsectionname]} % will become option (was \v!section-1)
+\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option
+%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option
+
+% We could use a commandhandler here but sections are somewhat special in the
+% sense that we have two ways of chaining: the main section (levels) as well
+% as rendering (head).
+
+% -2 = text
+% -1 = manual
+% 0 = block
+% +1 = structurelevel 1 .. n
+
+\newcount\maxstructuredepth
+
+\permanent\def\sectionlevel#1%
+ {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname}
+
+\permanent\def\namedsectionlevel#1#2% direct indirect
+ {\csname\??headlevel
+ \ifcsname\??headlevel#1\endcsname
+ #1%
+ \orelse\ifcsname\??headlevel#2\endcsname
+ #2%
+ \else
+ \v!none
+ \fi
+ \endcsname}
+
+\permanent\def\xthenamedheadlevel#1%
+ {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
+\setvalue{\??headlevel\v!block}{0}
+\setvalue{\??headlevel\v!none }{-1}
+\setvalue{\??headlevel\v!text }{-2}
+\setvalue{\??headlevel\v!head }{-3}
+
+\newtoks\everydefinesection
+
+\protected\def\definesection[#1]%
+ {\ifcsname\??headlevel#1\endcsname \else
+ \edef\currentsection{#1}% not used, will go
+ \edef\currenthead{#1}%
+ \global\advance\maxstructuredepth\plusone
+ \setevalue{\??headlevel#1}{\the\maxstructuredepth}%
+ \setstructurelevel{#1}{\sectionlevel{#1}}%
+ \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER
+ \the\everydefinesection
+ % so far for these default inheritances
+ \definemarking[#1]%
+ \ifnum\maxstructuredepth>\plusone
+ \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
+ \fi
+ \xdef\lastsectionname{#1}%
+ \ifx\firstsectionname\empty
+ \glet\firstsectionname\lastsectionname
+ \fi
+ \fi}
+
+\permanent\tolerant\protected\def\setupsection[#1]#*[#2]#*[#3]%
+ {\ifparameter#1\else
+ \ifcsname\??headlevel#1\endcsname
+ \strc_sectioning_setup_indeed[#1][#2][#3]%
+ \else
+ \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]%
+ \fi
+ \fi}
+
+\def\strc_sectioning_setup_indeed[#1][#2][#3]%
+ {\push_macro_currenthead
+ \ifthirdargument
+ \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now)
+ \setupcurrenthead[#3]%
+ \else
+ \edef\currenthead{#1}%
+ \setupcurrenthead[#2]%
+ \fi
+ \pop_macro_currenthead}
+
+% we share the parameters as sections are roots of heads so eventually we can
+% consider \definesection -> \definehead with one argument
+
+\appendtoks
+ % This is a rather practical default that we don't want to
+ % be part of the parent chain lookup mechanism; it's also
+ % mkii compatible. Somewhat weird that it's part of the
+ % top level structure but it will be flattened anyway.
+ \let\currenthead\currentsection %
+ \setheadparameter\c!textstyle {\directheadparameter\c!style}%
+ \setheadparameter\c!textcolor {\directheadparameter\c!color}%
+ \setheadparameter\c!numberstyle{\directheadparameter\c!style}%
+ \setheadparameter\c!numbercolor{\directheadparameter\c!color}%
+\to \everydefinesection
+
+% head -> head
+
+\permanent\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}}
+\permanent\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}}
+
+\permanent\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling}
+\permanent\def\sectionheadsection #1{\namedheadparameter{#1}\c!section}
+
+% head construction
+
+\protected\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed} % [ref] {nr} {title}
+\protected\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed} % [ref] {title}
+\protected\def\strc_sectioning_start {\dotripleempty\strc_sectioning_start_named_section} % [settings] [userdata] !!! also used at lua end
+
+\newconditional\currentstructureown
+
+\newtoks\everybeforehead % hook, todo: before/after keys
+\newtoks\everyafterhead % hook, todo: before/after keys
+
+\protected\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4%
+ {\settrue\currentstructureown
+ \triggerautostructurelevel
+ \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
+
+\protected\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant
+ {\setfalse\currentstructureown
+ \triggerautostructurelevel
+ \ifcondition\validassignment{#2}%
+ \expandafter\strc_sectioning_handle_nop_indeed_yes
+ \else
+ \expandafter\strc_sectioning_handle_nop_indeed_nop
+ \fi
+ {#1}{#2}}
+
+\protected\def\strc_sectioning_handle_nop_indeed_yes#1#2%
+ {\strc_sectioning_handle{#1}{#2}{}}
+
+\protected\def\strc_sectioning_handle_nop_indeed_nop#1#2#3%
+ {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
+
+\protected\def\strc_sectioning_start_named_section[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
+ {\push_macro_currentnamedsection
+ \push_macro_currentstructurereferenceprefix
+ \edef\currentnamedsection{#1}%
+ \setfalse\currentstructureown
+ %\globalpushmacro\currenthead % this does not work out well
+ \xdef\currenthead{#1}%
+ \setsystemmode\currenthead % new, also here now
+ \headparameter\c!beforesection % beware, no users vars set yet
+ \the\everybeforehead
+ \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
+ % potential: \bgroup (can be optional: grouped = yes)
+ \headparameter\c!insidesection}
+
+\protected\def\strc_sectioning_stop[#1]% !!! also used at lua end
+ {\dostoptagged
+ \dostoptagged
+ % potential: \egroup
+ %\globalpopmacro\currenthead % so we do a hard recover
+ \xdef\currenthead{#1}% recover
+ \headparameter\c!aftersection
+ \the\everyafterhead
+ \resetsystemmode\currenthead
+ \pop_macro_currentstructurereferenceprefix
+ \pop_macro_currentnamedsection} % new, also here now
+
+\permanent\let\dostarthead\strc_sectioning_start % used at lua end
+\permanent\let\dostophead \strc_sectioning_stop % used at lua end
+
+% \newconditional\structurereversesectionnumbers % todo: key/val
+
+\newconditional\c_strc_sectioning_to_list
+\newconditional\c_strc_sectioning_increment
+\newconditional\c_strc_sectioning_place
+\newconditional\c_strc_sectioning_empty
+\newconditional\c_strc_sectioning_hidden
+\newconditional\c_strc_sectioning_section
+
+\newconditional\headshownumber % public
+\newconditional\headisdisplay % public
+\newconditional\headissomewhere % public
+
+\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+
+\protected\def\strc_sectioning_initialize_increment
+ {\edef\currentheadincrement{\headparameter\c!incrementnumber}%
+ \ifcsname\??headincrement\currentheadincrement\endcsname
+ \lastnamedcs
+ \else
+ \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list
+ % \filterheadnumber
+ \fi}
+
+\permanent\protected\def\filterheadnumber
+ {\settrue\c_strc_sectioning_increment
+ \settrue\c_strc_sectioning_to_list
+ \ifx\currentproduct\empty
+ % todo : filter from other toc (number, file, title)
+ % use : \currentheadincrement as spec
+ \fi}
+
+\setvalue{\??headplace\v!yes}%
+ {\setfalse\c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden
+ \setfalse\c_strc_sectioning_section}
+
+\setvalue{\??headplace\v!empty}%
+ {\settrue \c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden
+ \setfalse\c_strc_sectioning_section}
+
+\setvalue{\??headplace\v!no}%
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden
+ \setfalse\c_strc_sectioning_section}
+
+\setvalue{\??headplace\v!hidden}%
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \settrue \c_strc_sectioning_hidden
+ \setfalse\c_strc_sectioning_section}
+
+\setvalue{\??headplace\v!section}%
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \settrue \c_strc_sectioning_hidden
+ \settrue \c_strc_sectioning_section}
+
+\protected\def\strc_sectioning_initialize_placement
+ {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes}
+
+\newmode\v!sectionnumber
+
+\def\dosetstructureheadnumbercontent
+ {\setsystemmode\v!sectionnumber
+ \settrue\headshownumber} % why ?
+
+\def\doresetstructureheadnumbercontent
+ {\resetsystemmode\v!sectionnumber
+ \setfalse\headshownumber} % why ?
+
+\protected\def\strc_sectioning_initialize_number
+ {\edef\p_number{\sectionblockparameter\c!number}%
+ \ifx\p_number\v!yes
+ \edef\p_number{\headparameter\c!number}%
+ \ifx\p_number\v!yes
+ \settrue\headshownumber
+ \else
+ \setfalse\headshownumber
+ \fi
+ \else
+ \setfalse\headshownumber
+ \fi}
+
+% Beware, we do need some node for anchoring marks and normally a zwnj will
+% do but it interferes so we deal with it at the \LUA\ end.
+
+\newtoks\everyheadsynchronization
+
+% \appendtoks
+% \currentstructuresynchronize
+% \to \everyheadsynchronization
+
+\let\currentstructuresynchronize\donothing
+
+\appendtoks
+ \currentstructuresynchronize
+ \glet\currentstructuresynchronize\donothing
+\to \everyheadsynchronization
+
+\protected\def\theheadsynchonization
+ {% no, interferes: \signalcharacter
+ \the\everyheadsynchronization}
+
+% BEWARE: \marking[section]{my text} does not work as we use list indices instead
+% so we need a 'keep track of raw set option' (or maybe a funny internal prefix)
+
+\permanent\protected\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this}
+ {\strc_sectioning_delayed_flush
+ \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}}
+
+\let\deepstructurenumbercommand\relax
+\let\deepstructuretitlecommand \relax
+
+\permanent\protected\def\fullheadnumber
+ {\edef\currentheadlabeltag{\currentsectionblock\c!label}%
+ \dostarttagged\t!sectionnumber\empty
+ \labeltexts
+ {\headparameter\currentheadlabeltag}
+ {\ifx\deepstructurenumbercommand\relax
+ \structurenumber
+ \else
+ \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}%
+ \fi}%
+ \dostoptagged}
+
+\permanent\protected\def\fullheadtitle
+ {\dostarttagged\t!sectiontitle\empty
+ \ifx\deepstructuretitlecommand\relax
+ \structuretitle
+ \else
+ \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}%
+ \fi
+ \dostoptagged}
+
+\let\currenthead \empty
+\let\currentheadcoupling\empty
+\let\currentheadsection \empty
+\let\currentheadlevel \!!zerocount
+\let\currentheadcounter \!!zerocount
+
+\let\strc_show_used\relax
+
+\installtextracker
+ {structures.showused}
+ {\let\strc_show_used\clf_showstructure}
+ {\let\strc_show_used\relax}
+
+\appendtoks
+ \strc_show_used
+\to \everystoptext
+
+\permanent\protected\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care
+\permanent\protected\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care
+
+\protected\def\strc_sectioning_report{\clf_reportstructure}
+
+\ifdefined\strc_rendering_initialize_style_and_color \else
+
+ \protected\def\strc_rendering_initialize_style_and_color#1#2%
+ {\dontconvertfont
+ \useheadstyleandcolor\c!style\c!color
+ \useheadstyleandcolor#1#2%
+ \setupinterlinespace}
+
+\fi
+
+\def\strc_sectioning_place_head_text[#1]%
+ {\dontleavehmode
+ \begingroup
+ \protected\def\\{\space}% messy here, but the default (and needs to be grouped)
+ \global\settrue\headisdisplay % triggers interlinespace checking
+ \edef\currenthead{#1}%
+ \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
+ \relax
+ \getspecificstructuretitle{\thenamedheadlevel{#1}}%
+ \endgraf
+ \endgroup}
+
+\def\strc_sectioning_place_head_number[#1]%
+ {\dontleavehmode
+ \begingroup
+ \global\settrue\headisdisplay % triggers interlinespace checking
+ \edef\currenthead{#1}%
+ \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
+ \relax
+ \getfullstructurenumber{\thenamedheadlevel{#1}}%
+ \endgraf
+ \endgroup}
+
+\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi
+
+\newtoks\everybeforesectionheadhandle
+\newtoks\everyaftersectionheadhandle
+
+\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller)
+ {\xdef\currenthead {#1}%
+ \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}%
+ \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}%
+ \xdef\currentheadlevel {\sectionlevel \currentheadsection}%
+ %
+ %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}%
+ %
+ \strc_sectioning_initialize_autolevel
+ \strc_sectioning_initialize_increment
+ \strc_sectioning_initialize_placement
+ \strc_sectioning_initialize_number
+ %
+ \the\everybeforesectionheadhandle
+ %
+ % todo: also mark (for header)
+ %
+ % we might remove the lower level
+ %
+ % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}%
+ %
+% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call
+ %
+ % \currentstructuresynchronize % will move
+ %
+ \let\getheadnumber\empty
+ \let\getheadtitle \empty
+ \let\getheadsyncs \empty
+ \ifconditional\c_strc_sectioning_increment
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \ifconditional\headshownumber
+ \let\getheadnumber\fullheadnumber
+ \strc_rendering_place_head_number_and_text
+ \else
+ \strc_rendering_place_head_text
+ \fi
+ \dostoptagged
+ \strc_sectioning_after_yes
+ \orelse\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs\theheadsynchonization
+ \ifconditional\c_strc_sectioning_section
+ \strc_rendering_place_head_section
+ \else
+ \strc_rendering_place_head_hidden % only something when tracing
+ \fi
+ \dostoptagged
+ \else
+ \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_empty % just flush 'm
+ \dostoptagged
+ \strc_sectioning_after_nop
+ \fi
+ \else
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \strc_rendering_place_head_text
+ \dostoptagged
+ \strc_sectioning_after_yes
+ \orelse\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \let\getheadsyncs\theheadsynchonization
+ \dostarttagged\t!sectioncaption\empty
+ \ifconditional\c_strc_sectioning_section
+ \strc_rendering_place_head_section
+ \else
+ \strc_rendering_place_head_hidden % only something when tracing
+ \fi
+ \dostoptagged
+ \else
+ % do nothing / should be vbox to 0pt
+ \strc_sectioning_before_nop
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs\theheadsynchonization
+ \strc_rendering_place_head_empty % just flush 'm
+ \dostoptagged
+ \strc_sectioning_after_nop
+ \fi
+ \fi
+ %
+ \the\everyaftersectionheadhandle
+ %
+ \setfalse\c_strc_sectioning_ignore_page
+ % ignorespaces prevents spaces creeping in when after=\dontleavehmode
+ \dostarttagged\t!sectioncontent\empty
+ \ifx\currentstructureplaceholder\empty
+ \ifconditional\headisdisplay
+ \doubleexpandafter\ignorespaces
+ \else
+ \doubleexpandafter\ignorepars
+ \fi
+ \else
+ \expandafter\strc_sectioning_placeholder
+ \fi}
+
+%D \starttyping
+%D \startsubject[placeholder=todo,title=one]
+%D whatever one
+%D \stopsubject
+%D \stoptyping
+
+\def\strc_sectioning_placeholder
+ {\placeholder[\currentstructureplaceholder]%
+ \gobblenested{\e!start\currenthead}{\e!stop\currenthead}{\e!stop\currenthead}}
+
+% typesetting (the getters are public)
+
+\protected\def\strc_rendering_place_head_number_and_text
+ {\setheadmarking
+ \getheadnumber/\getheadtitle
+ \getheadsyncs}
+
+\protected\def\strc_rendering_place_head_text
+ {\setheadmarking
+ \getheadtitle
+ \getheadsyncs}
+
+\protected\def\strc_rendering_place_head_empty
+ {\setheadmarking
+ \getheadsyncs}
+
+\installcorenamespace{hiddenheadattr}
+\installcorenamespace{hiddenheadsync}
+
+% todo: when in the page builder we need to resolve the marking immediately
+% because otherwise we have an async
+
+\newbox\b_sectioning_delayed
+
+\def\strc_sectioning_delayed_flush
+ {\ifvoid\b_sectioning_delayed\else
+ \smashedbox\b_sectioning_delayed
+ \fi}
+
+\protected\def\strc_rendering_place_head_section % see hidden below
+ {\global\setbox\b_sectioning_delayed\hpack\bgroup
+ \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
+ \hpack\headreferenceattributes{}% also does the mark
+ \theheadsynchonization
+ \egroup}
+
+\protected\def\strc_rendering_place_head_hidden % maybe trialtypesetting check
+ {\setxvalue{\??hiddenheadattr\currenthead}%
+ {\headreferenceattributes}% can be used when making a box
+ \setxvalue{\??hiddenheadsync\currenthead}%
+ {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax
+ \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
+ \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference
+ \theheadsynchonization}} % and it's a node anyway
+
+\permanent\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname}
+\permanent\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname}
+
+\permanent\protected\def\placerawheaddata [#1]{\synchronizehead{#1}}
+\permanent\protected\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}}
+\permanent\protected\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}}
+
+\permanent\protected\def\repeathead[#1]%
+ {\begingroup
+ \setupinteraction[\c!state=\v!stop]%
+ \def\currenthead{#1}
+ \strc_sectioning_initialize_placement
+ \strc_sectioning_initialize_number
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs \relax
+ \def\getheadtitle {\getmarking[#1]}
+ \def\getheadnumber{\getmarking[#1\v!number]}
+ \strc_sectioning_before_yes
+ \ifconditional\headshownumber
+ \strc_rendering_place_head_number_and_text
+ \else
+ \strc_rendering_place_head_text
+ \fi
+ \dostoptagged
+ \strc_sectioning_after_yes
+ \endgroup}
+
+% \setuphead[chapter][placehead=hidden]
+% \chapter {test}
+%
+% %(\synchronizehead{chapter}) % \getheadsyncs
+% %(\getfullstructurenumber{\thenamedheadlevel{chapter}})
+% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}})
+%
+% (\placerawheaddata [chapter])
+% (\placerawheadnumber[chapter])
+% (\placerawheadtext [chapter])
+
+% pagebreaks
+
+\letvalue{\??headmarknop\v!page }\donothing
+\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarknop\s!unknown}\donothing
+
+\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks}
+\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarkyes\s!unknown}\donothing
+
+\def\strc_sectioning_check_layout
+ {\edef\p_page{\headparameter\c!page}%
+ \ifx\p_page\empty
+ \strc_sectioning_check_layout_nop
+ \else
+ \strc_sectioning_check_layout_yes
+ \fi}
+
+\def\strc_sectioning_check_layout_nop
+ {\expandnamespaceparameter\??headmarknop\headparameter\c!marking\s!unknown}
+
+\def\strc_sectioning_check_layout_yes
+ {\page[\p_page]%
+ \expandnamespaceparameter\??headmarkyes\headparameter\c!marking\s!unknown
+ \edef\p_header{\headparameter\c!header}%
+ \ifx\p_header\empty \else
+ \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing
+ \fi
+ \edef\p_text{\headparameter\c!text}%
+ \ifx\p_text\empty \else
+ \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing
+ \fi
+ \edef\p_footer{\headparameter\c!footer}%
+ \ifx\p_footer\empty \else
+ \doifelselayouttextline\v!footer{\normalexpanded{\setuplayouttext[\v!footer][\c!state=\p_footer]}}\donothing
+ \fi}
+
+\newcount \c_strc_sectioning_preceding_level \c_strc_sectioning_preceding_level\plusone
+\newconditional\c_strc_sectioning_auto_break \settrue\c_strc_sectioning_auto_break
+\newconditional\c_strc_sectioning_ignore_page
+\newsignal \s_strc_sectioning_continuous_signal
+
+\protected\def\strc_sectioning_inject_continuous_signal
+ {\ifhmode
+ \hskip\s_strc_sectioning_continuous_signal\relax
+ \fi}
+
+% \let\dotagsectionlevel\relax
+
+\def\strc_sectioning_before_yes
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_yes
+ \headparameter\c!inbetween
+ \dostarttaggedchained\t!section\currenthead\??head
+% \dotagsectionlevel
+ }
+
+\def\strc_sectioning_before_nop
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_nop
+ \headparameter\c!inbetween
+ \dostarttagged\currenthead\empty} % this is a weird one .. needs checking
+
+\def\strc_sectioning_empty_correction
+ {\ifconditional\c_strc_sectioning_empty
+ % this needs checking
+ \penalty\plustenthousand
+ \vskip-\lineheight
+ \kern\zeropoint
+ \prevdepth\strutdepth
+ \fi}
+
+\def\strc_sectioning_after_nop
+ {}
+
+\def\strc_sectioning_check_before#1%
+ {\ifhmode
+ \scratchcounter\lastpenalty
+ \unpenalty % no beauty in this
+ \ifdim\lastskip=\s_strc_sectioning_continuous_signal
+ % no page break
+ \ifconditional\c_strc_sectioning_ignore_page
+ \setfalse\c_strc_sectioning_ignore_page
+ \else
+ \global\c_strc_sectioning_preceding_level\currentheadlevel
+ \nobreak
+ \fi
+ % \global\settrue\c_strc_rendering_continuous
+ \else
+ \penalty\scratchcounter
+ % \global\setfalse\c_strc_rendering_continuous
+ #1%
+ \fi
+ \else
+ % \global\setfalse\c_strc_rendering_continuous
+ #1%
+ \fi}
+
+%permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
+%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
+
+\permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax}
+%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
+\permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax}
+
+\let\previoushead\empty
+
+\def\strc_sectioning_handle_page_nop
+ {\edef\p_continue{\headparameter\c!continue}%
+ \ifx\p_continue\v!yes
+ \ifx\currenthead\previoushead % not really needed
+ \strc_sectioning_check_layout
+ \orelse\ifnum\previoussectioncountervalue=\zerocount
+ \strc_sectioning_check_layout
+ \orelse\ifnum\currentsectioncountervalue>\zerocount
+ \strc_sectioning_check_layout
+ \fi
+ \else
+ \strc_sectioning_check_layout
+ \fi
+ \glet\previoushead\currenthead}
+
+
+\def\strc_sectioning_handle_page_yes
+ {\ifconditional\c_strc_sectioning_ignore_page
+ \setfalse\c_strc_sectioning_ignore_page
+ \else
+ % beware, these numbers are not yet know here
+ \strc_sectioning_handle_page_nop
+ \edef\p_aligntitle{\headparameter\c!aligntitle}%
+ \ifx\p_aligntitle\v!float
+ \ifconditional\c_strc_sectioning_auto_break
+ \spac_vspacing_same_page\currentheadlevel\zerocount
+ \fi
+ \headparameter\c!before\relax
+ \indent
+ \else
+ \page_otr_command_flush_side_floats
+ \ifconditional\c_strc_sectioning_auto_break
+ \spac_vspacing_same_page\currentheadlevel\zerocount
+ \fi
+ \headparameter\c!before\relax
+ \fi
+ \global\c_strc_sectioning_preceding_level\currentheadlevel
+ \fi
+ \glet\previoushead\currenthead}
+
+\def\strc_sectioning_depth_correction
+ {\ifvmode
+ \edef\p_depthcorrection{\headparameter\c!depthcorrection}%
+ \ifx\p_depthcorrection\v!strut
+ \prevdepth\strutdepth
+ \fi
+ \fi}
+
+\def\strc_sectioning_after_yes
+ {\ifconditional\headisdisplay
+ \ifconditional\c_strc_sectioning_auto_break
+ \spac_vspacing_same_page\currentheadlevel\plusone
+ \fi
+ \strc_sectioning_empty_correction
+ \headparameter\c!after
+ \strc_sectioning_depth_correction
+ \fi}
+
+\protected\def\strc_sectioning_prevent_page_break % see strc-con
+ {\ifconditional\c_strc_sectioning_auto_break
+ \spac_vspacing_same_page\currentheadlevel\plustwo
+ \fi}
+
+
+% We do support negative numbers but it can have side effects that we won't catch:
+%
+% \chapter{some} \setupheadnumber[chapter][3] \chapter{more}
+% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d}
+
+\def\thenamedheadlevel#1%
+ {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
+\permanent\protected\def\setupheadnumber
+ {\dodoubleargument\strc_sectioning_setup_number}
+
+\def\strc_sectioning_setup_number[#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}}}}
+
+% The previous macro is been replaced by the expandable:
+
+\permanent\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}}
+\permanent\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}}
+
+\permanent\protected\def\headnumber
+ {\dodoubleempty\strc_sectioning_number}
+
+\def\strc_sectioning_number[#1][#2]% simple case is just a number
+ {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}}
+
+\permanent\protected\def\someheadnumber
+ {\dodoubleempty\strc_sectioning_number_some}
+
+\def\strc_sectioning_number_some[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \edef\currenthead{#1}%
+ \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}%
+ \endgroup}
+
+\aliased\let\sectioncountervalue\structurevalue
+
+\def\currentheadtext{obsolete,\space use marks}
+
+% list references, will be redone in lua when we need it
+
+\let\startlistreferences\relax
+\let\stoplistreferences \relax
+
+% experimental
+
+\newconditional\c_strc_sectioning_auto_levels
+
+\appendtoks
+ \settrue\c_strc_sectioning_auto_levels
+\to \everyenableelements
+
+\protected\def\strc_sectioning_initialize_autolevel
+ {\ifconditional\c_strc_sectioning_auto_levels
+ \clf_autonextstructurelevel\currentheadlevel\relax
+ \global\setfalse\c_strc_sectioning_auto_levels
+ \fi}
+
+\permanent\protected\def\triggerautostructurelevel
+ {\global\settrue\c_strc_sectioning_auto_levels}
+
+\permanent\protected\def\finalizeautostructurelevels
+ {\clf_autofinishstructurelevels}
+
+\permanent\protected\def\finalizeautostructurelevel
+ {\dostoptagged
+ \dostoptagged}
+
+\appendtoks
+ \finalizeautostructurelevels
+\to \everystoptext
+
+\stopcontextdefinitioncode
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/strc-syn.mkxl b/tex/context/base/mkiv/strc-syn.mkxl
new file mode 100644
index 000000000..130d1737a
--- /dev/null
+++ b/tex/context/base/mkiv/strc-syn.mkxl
@@ -0,0 +1,658 @@
+%D \module
+%D [ file=strc-syn,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Synonyms and Sorting,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting}
+
+\registerctxluafile{strc-syn}{}
+
+%D Although we could nowadays build this on top of regular lists we keep this
+%D more efficient variant around. Eventually we can add some options to lists
+%D that also provide such functionality but at the cost of much more overhead.
+%D
+%D We show a usage of both synonyms and sorts, which are deep down variants of
+%D so called simple lists. A definition looks like this:
+%D
+%D \startbuffer
+%D \definesynonyms
+%D [myabbreviation]
+%D
+%D \setupsynonyms
+%D [myabbreviation]
+%D [headstyle=bold,
+%D headcolor=darkred,
+%D synonymstyle=boldslanted,
+%D synonymcolor=darkblue,
+%D textstyle=slanted,
+%D textcolor=darkgreen,
+%D style=normal,
+%D color=darkyellow]
+%D
+%D \definesorting
+%D [mylogo]
+%D
+%D \setupsorting
+%D [mylogo]
+%D [style=bold,
+%D color=darkmagenta]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D More complex definitions involves commands to call up meanings and such. The
+%D use of the defined commands is as follows: \
+%D
+%D \startbuffer
+%D \myabbreviation [FIRST] {TheFirst} {The First Words}
+%D \myabbreviation [SECOND] {TheSecond} {The Second Words}
+%D \myabbreviation [THIRD] {TheThird} {The Third Words}
+%D
+%D \mylogo [FOURTH] {TheFourth}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D By default a synonym is just typeset and flagges as being used, so that in
+%D a list it wil be shows with its meaning. You can however also expand the
+%D meaning automatically at first use:
+%D
+%D \startbuffer
+%D \setupsynonyms[myabbreviation][alternative=first]
+%D
+%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH.
+%D
+%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D We can change the order, as demonstrated in:
+%D
+%D \startbuffer
+%D \resetshownsynonyms[myabbreviation]
+%D
+%D \setupsynonyms[myabbreviation][alternative=last]
+%D
+%D We have \FIRST\ and \THIRD\ or \FOURTH.
+%D
+%D We have \FIRST\ and \THIRD\ or \FOURTH.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D A list is called up with:
+%D
+%D \startbuffer
+%D \placelistofsynonyms[myabbreviation]
+%D
+%D \placelistofsorts[mylogo]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The lists are constructions (like descriptions are) and can be set up
+%D likewise.
+
+% todo: add 'define only' option to descriptions, then add sorting (also based on key)
+% and call to definition -> replaces this module
+
+\unprotect
+
+% split but common in lua
+
+\permanent\protected\def\preprocessexpansion#1#2#3#4% do this at the lua end if still needed
+ {\ifx#1\s!xml
+ \xmlstartraw
+ \xdef#2{#4}%
+ \xmlstopraw
+ \glet#3\s!xml
+ \else
+ \ifx#1\v!yes
+ \xdef#2{#4}%
+ \else
+ \xdef#2{\detokenize{#4}}%
+ \fi
+ \glet#3\s!tex
+ \fi}
+
+%D We now use a simple list variant:
+
+\installcorenamespace {simplelist}
+
+\installcommandhandler \??simplelist {simplelist} \??simplelist
+
+\let\setupsimplelists\setupsimplelist
+
+\setupsimplelists[%
+ %c!title=,
+ %c!text=,
+ %
+ %c!style=,
+ %c!color=,
+ %c!command=,
+ %c!align=,
+ %
+ %c!headstyle=,
+ %c!headcolor=,
+ %c!headalign=,
+ %
+ %c!titlestyle=,
+ %c!titlecolor=,
+ %c!titlecommand=,
+ %c!titleleft=,
+ %c!titleright=,
+ %
+ %c!closesymbol=,
+ %c!closecommand=,
+ %
+ \c!alternative=\v!left,
+ \c!display=\v!yes,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
+ %c!hang=,
+ %c!sample=,
+ \c!margin=\v!no,
+ \c!before=\startpacked,
+ \c!inbetween=\blank,
+ \c!after=\stoppacked,
+ %c!indentnext=,
+ %c!indenting=,
+ %
+ \c!expansion=\v!no,
+ %c!xmlsetup=,
+ %s!catcodes=,
+ \s!language=\currentmainlanguage,
+]
+
+\appendtoks
+ \setfalse\c_strc_constructions_define_commands
+ \ifx\currentsimplelistparent\empty
+ \defineconstruction[\currentsimplelist][\s!handler=\v!simplelist,\c!level=1]%
+ \else
+ \defineconstruction[\currentsimplelist][\currentsimplelistparent][\s!handler=\v!simplelist,\c!level=1]%
+ \fi
+ \settrue\c_strc_constructions_define_commands
+\to \everydefinesimplelist
+
+\setuvalue{\??constructioninitializer\v!simplelist}%
+ {\let \currentsimplelist \currentconstruction
+ \enforced\let\constructionparameter \simplelistparameter
+ \enforced\let\constructionnamespace \??simplelist
+ \enforced\let\detokenizedconstructionparameter\detokenizedsimplelistparameter
+ \enforced\let\letconstructionparameter \letsimplelistparameter
+ \enforced\let\useconstructionstyleandcolor \usesimpleliststyleandcolor
+ \enforced\let\setupcurrentconstruction \setupcurrentsimplelist}
+
+\setuvalue{\??constructionfinalizer\v!simplelist}%
+ {}
+
+\setuvalue{\??constructiontexthandler\v!simplelist}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \the\everyconstruction
+ \constructionparameter\c!headcommand
+ {\strut
+ \currentsimplelistentry}%
+ \endgroup}
+
+% And we build on top of this.
+
+\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi
+\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi
+
+\definesimplelist
+ [\v!synonym]
+ [\c!state=\v!start,
+ %\c!synonymstyle=,
+ %\c!textstyle=,
+ %\c!headstyle=,
+ %\c!headcolor=,
+ %\c!criterium=,
+ \c!location=\v!left,
+ \c!width=5\emwidth,
+ \c!distance=\zeropoint,
+ %\c!sample=,
+ %\c!hang=,
+ %\c!align=,
+ %\c!before=,
+ %\c!inbetween=,
+ %\c!after=,
+ \c!indentnext=\v!no,
+ %\c!expansion=,
+ \c!method=]
+
+\aliased\let\setupsynonyms\setupsimplelist
+
+\permanent\tolerant\protected\def\definesynonyms[#1]#*[#2]#*[#3]#*[#4]% name plural \meaning \use
+ {\ifnum\lastarguments=\plusfour
+ \protected\instance\def#4##1{\strc_synonyms_insert{#1}{##1}}% name tag
+ \frozen\instance\setuvalue{#1}{\definesynonym[\v!no][#1]}% \name
+ \else
+ \frozen\instance\setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name
+ \fi
+ \ifnum\lastarguments>\plustwo
+ \protected\frozen\instance\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning
+ \fi
+ \edef\currentsynonym{#1}%
+ %
+ %\checksynonymparent
+ %\setupcurrentsynonym[\s!single={#1},\s!multi={#2}]%
+ \setfalse\c_strc_constructions_define_commands
+ \definesimplelist
+ [\currentsynonym]%
+ [\v!sorting]
+ [\s!single={#1},%
+ \s!multi={#2}]%
+ \settrue\c_strc_constructions_define_commands
+ \ifparameter#2\or
+ %
+ \presetheadtext[#2=\Word{#2}]% changes the \if...argument
+ %
+ % These will go away. Actually the overloads catched this empty case!
+ %
+ \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsynonyms[#1]}% obsolete definition
+ \instance\setuvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument
+ \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}%
+ \fi}
+
+\permanent\tolerant\protected\def\definesynonym[#1]#*[#2]#*[#3]%
+ {\begingroup
+ \edef\currentsynonymoption{#1}%
+ \edef\currentsynonym{#2}%
+ \edef\currentsynonymtag{#3}%
+ \strc_synonyms_define_entry}
+
+\def\strc_synonyms_define_entry#1#2%
+ {\let\currentsimplelist\currentsynonym
+ \ifempty\currentsynonymtag
+ \edef\currentsynonymtag{#1}%
+ \fi
+ \ifempty\currentsynonymtag \else
+ % this is not that efficient, esp when we load a big list
+ \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}%
+ \preprocessexpansion\currentsynonymexpansion\m_synonyms_text \currentsynonymcoding{#1}%
+ \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#2}%
+ %
+ \clf_registersynonym
+ {\currentsynonym}%
+ {synonym}%
+ {%
+ metadata {%
+ catcodes \catcodetable
+ coding {\currentsynonymcoding}%
+ \ifx\currentsynonymcoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ }%
+ definition {%
+ tag {\currentsynonymtag}%
+ synonym {\m_synonyms_text}%
+ meaning {\m_synonyms_meaning}%
+ % used false
+ }%
+ }%
+ \relax
+ \ifx\currentsynonymoption\v!yes
+ \instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}%
+ \fi
+ \fi
+ \endgroup}
+
+\permanent\tolerant\protected\def\registersynonym [#1]#*[#2]{\clf_registerusedsynonym{#1}{#2}}
+\permanent \protected\def\currentsynonymname {\clf_synonymname{\currentsimplelist}{\currentsynonymtag}}
+\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning{\currentsimplelist}{\currentsynonymtag}}
+\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused{\currentsimplelist}{\currentsynonymtag}}
+\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}}
+\permanent \protected\def\resetusedsynonyms [#1]{\clf_resetusedsynonyms{#1}}
+\permanent \protected\def\resetshownsynonyms [#1]{\clf_resetshownsynonyms{#1}}
+
+\aliased\let\rawsynonymname \clf_synonymname
+\aliased\let\rawsynonymmeaning\clf_synonymmeaning
+
+\installcorenamespace{simplelistalternative} % specific ways of rendering a list
+\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local)
+
+\installcommandhandler \??simplelistalternative {simplelistalternative} \??simplelistalternative
+
+\setupsimplelist
+ [\v!synonym]
+ [\c!alternative=\v!normal]
+
+\protected\def\strc_synonyms_insert_meaning#1#2% name tag
+ {\dontleavehmode % otherwise we don't get it right at the beginning of a par
+ \begingroup
+ \def\currentsimplelist{#1}%
+ \def\currentsynonymtag{#2}%
+ \fastsetup{\??simplelistrenderings::\v!text}%
+ \endgroup}
+
+\protected\def\strc_synonyms_insert#1#2% name tag
+ {\dontleavehmode % otherwise we don't get it right at the beginning of a par
+ \begingroup
+ \edef\currentsimplelist{#1}%
+ \let\currentsynonym\currentsimplelist % for a while
+ \def\currentsynonymtag{#2}%
+ \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}%
+ \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative
+ {\let\currentsimplelistalternative\v!normal}%
+ \fastsetup{\??simplelistrenderings:\v!synonym:\currentsimplelistalternative}%
+ \normalexpanded{\endgroup\simplelistparameter\c!next}}
+
+% \setupsimplelistalternative
+% [\c!command=\directsimplelistparameter\c!command]
+
+\definesimplelistalternative
+ [\v!normal]
+ [\c!inbetween=\space,
+ \c!left=(,
+ \c!right=)]
+
+\definesimplelistalternative
+ [\v!first]
+ [\v!normal]
+
+\definesimplelistalternative
+ [\v!last]
+ [\v!normal]
+
+\startsetups[\??simplelistrenderings::\v!synonym]
+ \begingroup
+ \dostarttaggedchained\t!synonym\currentsynonym\??simplelist
+ \dotagsynonym
+ \usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor
+ \simplelistparameter\c!synonymcommand{\currentsynonymname}%
+ \dostoptagged
+ \endgroup
+\stopsetups
+
+\startsetups[\??simplelistrenderings::\v!text]
+ \begingroup
+ \usehyphensparameter\simplelistparameter
+ \usesimpleliststyleandcolor\c!textstyle\c!textcolor
+ \simplelistparameter\c!textcommand{\currentsynonymmeaning}%
+ \endgroup
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!normal]
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!first]
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ \doifelsecurrentsynonymshown \donothing {
+ \simplelistalternativeparameter\c!inbetween
+ \simplelistalternativeparameter\c!left
+ \fastsetup{\??simplelistrenderings::\v!text}
+ \simplelistalternativeparameter\c!right
+ }
+\stopsetups
+
+\startsetups[\??simplelistrenderings:\v!synonym:\v!last]
+ \doifelsecurrentsynonymshown {
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ } {
+ \fastsetup{\??simplelistrenderings::\v!text}
+ \simplelistalternativeparameter\c!inbetween
+ \simplelistalternativeparameter\c!left
+ \fastsetup{\??simplelistrenderings::\v!synonym}
+ \simplelistalternativeparameter\c!right
+ }
+\stopsetups
+
+\permanent\tolerant\protected\def\placelistofsynonyms[#1]#*[#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \doifelsecommandhandler\??simplelist\currentsimplelist
+ {\strc_constructions_initialize{#1}%
+ \setupcurrentsimplelist[#2]%
+ \let\synonymentry\strc_synonym_normal
+ % so we can hook tabulate into before and after
+ \normalexpanded{\simplelistparameter\c!before
+ \noexpand\clf_processsynonyms
+ {#1}%
+ {%
+ criterium {\simplelistparameter\c!criterium}%
+ language {\simplelistparameter\s!language}%
+ method {\simplelistparameter\c!method}%
+ }%
+ \relax
+ \simplelistparameter\c!after}%
+ \relax}%
+ {}% todo: message that invalid
+ \endgroup}
+
+\permanent\tolerant\protected\def\completelistofsynonyms[#1]#*[#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \doifelsecommandhandler\??simplelist\currentsimplelist
+ {\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}%
+ \strc_synonyms_place_list[#1][#2]%
+ \page
+ \stopnamedsection}%
+ {}% todo: message that invalid
+ \endgroup}
+
+\protected\def\strc_synonym_normal#1#2#3#4%
+ {\begingroup
+ \def\currentsimplelistentry{#3}%
+ \csname\??constructionstarthandler\v!construction\endcsname
+ #4%
+ \csname\??constructionstophandler\v!construction\endcsname
+ \endgroup}
+
+%D Sorting (a simplified version of synonym).
+
+\definesimplelist
+ [\v!sorting]
+ [\c!state=\v!start,
+ %\c!command=, % we test for defined !
+ %\c!criterium=,
+ %\c!style=,
+ \c!before=\startpacked,
+ \c!after=\stoppacked,
+ %\c!expansion=,
+ \c!method=]
+
+\aliased\let\setupsorting\setupsimplelist
+
+% if #3=\relax or \v!none, then no command but still protected
+
+\permanent\tolerant\protected\def\definesorting[#1]#*[#2]#*[#3]%
+ {\ifnum\lastarguments=\plusthree
+ \doifnot{#3}\v!none
+ {\ifx#3\relax \else
+ \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}%
+ \fi}%
+ \frozen\instance\setuvalue{#1}{\definesort[\v!no][#1]}%
+ \else
+ \frozen\instance\setuvalue{#1}{\definesort[\v!yes][#1]}%
+ \fi
+ \edef\currentsorting{#1}%
+ \setfalse\c_strc_constructions_define_commands
+ \definesimplelist
+ [\currentsorting]%
+ [\v!sorting]
+ [\s!single={#1},%
+ \s!multi={#2}]%
+ \settrue\c_strc_constructions_define_commands
+ \ifparameter#2\or
+ %
+ \presetheadtext[#2=\Word{#2}]% changes the \if...argument
+ %
+ % These will go away. Actually the overloads catched this empty case!
+ %
+ %
+ \presetheadtext[#2=\Word{#2}]% after \ifthirdargument -)
+ %
+ \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition
+ \instance\setuvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}%
+ \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}%
+ \fi}
+
+\permanent\tolerant\protected\def\definesort[#1]#*[#2]#*[#3]%
+ {\begingroup
+ \edef\currentsortingoption{#1}%
+ \edef\currentsorting{#2}%
+ \edef\currentsortingtag{#3}%
+ \strc_sorting_define_entry}
+
+\def\strc_sorting_define_entry#1%
+ {\let\currentsimplelist\currentsimplelist
+ \ifempty\currentsortingtag
+ \edef\currentsortingtag{#1}%
+ \fi
+ \ifempty\currentsortingtag \else
+ \edef\currentsortingexpansion{\simplelistparameter\c!expansion}%
+ \preprocessexpansion\currentsortingexpansion\currentsortingtext\currentsortingcoding{#1}%
+ \clf_registersynonym
+ {\currentsorting}%
+ {sorting}%
+ {%
+ metadata {%
+ catcodes \catcodetable
+ coding {\currentsortingcoding}%
+ \ifx\currentsortingcoding\s!xml
+ xmlroot {\xmldocument}%
+ \fi
+ }%
+ definition {%
+ tag {\currentsortingtag}%
+ synonym {\currentsortingtext}%
+ % used false
+ }%
+ }%
+ \relax
+ \ifx\currentsortingoption\v!yes
+ \instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}%
+ \fi
+ \fi
+ \endgroup}
+
+\permanent\protected\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}}
+\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}}
+\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}}
+
+\setupsimplelist
+ [\v!sorting]
+ [\c!alternative=\v!normal]
+
+\protected\def\strc_sorting_insert#1#2% name tag
+ {\dontleavehmode % otherwise we don't get it right at the beginning of a par
+ \begingroup
+ % no kap currently, of .. we need to map cap onto WORD
+ \edef\currentsorting{#1}%
+ \edef\currentsortingtag{#2}%
+ \let\currentsimplelist\currentsorting
+ \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}%
+ \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative
+ {\let\currentsimplelistalternative\v!normal}%
+ \fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}%
+ \normalexpanded{\endgroup\simplelistparameter\c!next}}
+
+% or:
+%
+% \doifelsesetups{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}
+% {\fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}}
+% {\fastsetup{\??simplelistrenderings:\v!sorting:\v!normal}}
+
+\startsetups [\??simplelistrenderings:\v!sorting:\v!normal]
+ \fastsetup{\??simplelistrenderings::\v!sorting}%
+\stopsetups
+
+\startsetups [\??simplelistrenderings::\v!sorting]
+ \begingroup
+ \dostarttaggedchained\t!sorting\currentsorting\??simplelist
+ \dotagsorting
+ \usesimpleliststyleandcolor\c!style\c!color
+ \currentsortingname
+ \dostoptagged
+ \endgroup
+\stopsetups
+
+\permanent\tolerant\protected\def\registersort[#1]#*[#2]%
+ {\clf_registerusedsynonym{#1}{#2}}
+
+% before after
+%
+% maybe just 'commandset' and then combine
+
+\permanent\tolerant\protected\def\placelistofsorts[#1]#*[#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \strc_constructions_initialize{#1}%
+ \setupcurrentsimplelist[#2]%
+ \edef\p_simplelist_command{\simplelistparameter\c!command}%
+ \ifx\p_simplelist_command\empty
+ \let\synonymentry\strc_sorting_normal
+ \else
+ \let\synonymentry\strc_sorting_command
+ \fi
+ % so we can hook tabulate into before and after
+ \normalexpanded{\simplelistparameter\c!before
+ \noexpand\clf_processsynonyms
+ {#1}%
+ {%
+ criterium {\simplelistparameter\c!criterium}%
+ language {\simplelistparameter\s!language}%
+ method {\simplelistparameter\c!method}%
+ }%
+ \relax
+ \simplelistparameter\c!after}%
+ \endgroup}
+
+\permanent\tolerant\protected\def\completelistofsorts[#1]#*[#2]%
+ {\begingroup
+ \edef\currentsimplelist{#1}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}%
+ \strc_sorting_place_list[#1][#2]%
+ \page
+ \stopnamedsection
+ \endgroup}
+
+\def\strc_sorting_command#1#2#3#4% #4 is meaning but empty here
+ {\p_simplelist_command{#1}{#2}{#3}}
+
+\def\strc_sorting_normal#1#2#3#4% #4 is meaning but empty here
+ {\begingroup
+ \usesimpleliststyleandcolor\c!style\c!color
+ #3%
+ \endgroup
+ \par}
+
+%D Presets.
+
+% To be considered:
+%
+% \setupsimplelist
+% [\v!sorting]
+% [\c!headstyle=\simplelistparameter\c!synonymstyle,
+% \c!headcolor=\simplelistparameter\c!synonymcolor,
+% \c!style=\simplelistparameter\c!textstyle,
+% \c!color=\simplelistparameter\c!textcolor]
+
+\definesynonyms
+ [\v!abbreviation]
+ [\v!abbreviations]
+ [\infull]
+
+\setupsynonyms
+ [\v!abbreviation]
+ [\c!hyphens=\v!no, % new, not yet in setup definitions
+ \c!textstyle=\v!capital]
+
+\definesorting
+ [\v!logo]
+ [\v!logos]
+% [\logogram] % no
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/supp-box.lmt b/tex/context/base/mkiv/supp-box.lmt
index 61ec9b328..8a308f90f 100644
--- a/tex/context/base/mkiv/supp-box.lmt
+++ b/tex/context/base/mkiv/supp-box.lmt
@@ -29,7 +29,7 @@ local vlist_code = nodecodes.vlist
local glue_code = nodecodes.glue
local penalty_code = nodecodes.penalty
local glyph_code = nodecodes.glyph
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local indent_code = nodes.listcodes.indent
@@ -887,7 +887,7 @@ implement {
b = getwidth(n) > 0
break
end
- elseif id ~= localpar_code then
+ elseif id ~= par_code then
break
end
end
@@ -1239,3 +1239,83 @@ do
define_two("boxrangedp", "dp")
end
+
+do
+
+ local getbox = tex.getbox
+ local setfield = nodes.setfield
+ local getfield = nodes.getfield
+ local flush = nodes.flush
+ local copynode = nodes.copy
+
+ local function get(n,field,copy)
+ local b = getbox(n)
+ if b then
+ local p = getfield(b,field)
+ if copy then
+ p = copynode(p)
+ else
+ setfield(b,field)
+ end
+ context(p)
+ end
+ end
+
+ local function set(n,l,field)
+ local b = getbox(n)
+ if b then
+ setfield(b,field,l)
+ else
+ flush(l)
+ end
+ end
+
+ implement {
+ name = "prelistbox",
+ public = true,
+ usage = "value",
+ arguments = { "integer", '"pre"' },
+ actions = get,
+ }
+
+ implement {
+ name = "postlistbox",
+ public = true,
+ usage = "value",
+ arguments = { "integer", '"post"' },
+ actions = get,
+ }
+
+ implement {
+ name = "prelistcopy",
+ public = true,
+ usage = "value",
+ arguments = { "integer", '"pre"', true },
+ actions = get,
+ }
+
+ implement {
+ name = "postlistcopy",
+ public = true,
+ usage = "value",
+ arguments = { "integer", '"post"', true },
+ actions = get,
+ }
+
+ implement {
+ name = "setprelistbox",
+ public = true,
+ usage = "value",
+ arguments = { "integer", "box", '"pre"' },
+ actions = set,
+ }
+
+ implement {
+ name = "setpostlistbox",
+ public = true,
+ usage = "value",
+ arguments = { "integer", "box", '"post"' },
+ actions = set,
+ }
+
+end
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index d26742a5b..4914b6818 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -29,7 +29,7 @@ local vlist_code = nodecodes.vlist
local glue_code = nodecodes.glue
local penalty_code = nodecodes.penalty
local glyph_code = nodecodes.glyph
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local indent_code = nodes.listcodes.indent
@@ -854,7 +854,7 @@ implement {
b = getwidth(n) > 0
break
end
- elseif id ~= localpar_code then
+ elseif id ~= par_code then
break
end
end
diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv
index b9835875d..16f093023 100644
--- a/tex/context/base/mkiv/supp-box.mkiv
+++ b/tex/context/base/mkiv/supp-box.mkiv
@@ -112,16 +112,16 @@
%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of
%D a box to zero. The most resolute one is presented first.
-\protected\def\smashbox#1%
- {\wd#1\zeropoint
- \ht#1\zeropoint
- \dp#1\zeropoint}
+% \protected\def\smashbox#1%
+% {\wd#1\zeropoint
+% \ht#1\zeropoint
+% \dp#1\zeropoint}
-\protected\def\smashboxed#1%
- {\wd#1\zeropoint
- \ht#1\zeropoint
- \dp#1\zeropoint
- \box#1\relax}
+% \protected\def\smashboxed#1%
+% {\wd#1\zeropoint
+% \ht#1\zeropoint
+% \dp#1\zeropoint
+% \box#1\relax}
%D \macros
%D {hsmashbox,vsmashbox}
@@ -170,6 +170,8 @@
\dp\c_boxes_register\zeropoint
\box\c_boxes_register}
+\let\smashboxed\smashedbox
+
%D \macros
%D {hsmash,vsmash,
%D hsmashed,vsmashed}
@@ -1105,8 +1107,8 @@
\protected\def\processtokens#1#2#3#4#5%
{\begingroup
\def\lastcharacter{\lastcharacter}% hm, recursive ?
+ \let\\\space
\def\space{ }%
- \let\\=\space
\def\before {#1}%
\def\between{#2}%
\def\after {#3}%
@@ -2263,9 +2265,9 @@
\scratchdimen\zeropoint
\def\docommand
{\advance\sizeofbox\scratchdimen
- \futurelet\next\dodocommand}%
+ \futurelet\nexttoken\dodocommand}%
\def\dodocommand
- {\ifx\next\bgroup
+ {\ifx\nexttoken\bgroup
\expanded{\egroup#1 to \the\sizeofbox}%
\else
\expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen
diff --git a/tex/context/base/mkiv/supp-box.mkxl b/tex/context/base/mkiv/supp-box.mkxl
index 4e29550e2..2ed9ea9c1 100644
--- a/tex/context/base/mkiv/supp-box.mkxl
+++ b/tex/context/base/mkiv/supp-box.mkxl
@@ -25,18 +25,6 @@
% \fixupboxesmode\plusone % gone: is now the default
-%D \macros
-%D {dontcomplain}
-%D
-%D The next macro suppresses over- and underfull messages which often makes sense
-%D when we deal with boxes.
-
-\protected\def\dontcomplain
- {\hbadness\plustenthousand
- \vbadness\plustenthousand
- \hfuzz \maxdimen
- \vfuzz \maxdimen}
-
%D This module implements some box manipulation macros. Some are quite simple, some
%D are more advanced and when understood well, all can be of use.
%D
@@ -47,6 +35,8 @@
%D not, you're in trouble). These shortcuts can be used like a dimension, opposite
%D to the core macros \type {\strutdepth} and alike, which are values.
+%D These will be overloaded in spac-ver:
+
\def\strutdp {\dp\strutbox}
\def\strutht {\ht\strutbox}
\def\strutwd {\wd\strutbox}
@@ -72,21 +62,21 @@
\newdimen\nextdepth
%D \macros
-%D {smashbox, smashedbox}
+%D {smashbox, smashboxed, smashedbox}
%D
%D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of
%D a box to zero. The most resolute one is presented first.
-\protected\def\smashbox#1%
- {\wd#1\zeropoint
- \ht#1\zeropoint
- \dp#1\zeropoint}
-
-\protected\def\smashboxed#1%
- {\wd#1\zeropoint
- \ht#1\zeropoint
- \dp#1\zeropoint
- \box#1\relax}
+% \permanent\protected\def\smashbox#1%
+% {\wd#1\zeropoint
+% \ht#1\zeropoint
+% \dp#1\zeropoint}
+%
+% \permanent\protected\def\smashboxed#1%
+% {\wd#1\zeropoint
+% \ht#1\zeropoint
+% \dp#1\zeropoint
+% \box#1\relax}
%D \macros
%D {hsmashbox,vsmashbox}
@@ -94,18 +84,18 @@
%D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or
%D vertical, one can use:
-\protected\def\hsmashbox#1%
- {\wd#1\zeropoint}
-
-\protected\def\vsmashbox#1%
- {\ht#1\zeropoint
- \dp#1\zeropoint}
+% \permanent\protected\def\hsmashbox#1%
+% {\wd#1\zeropoint}
+%
+% \permanent\protected\def\vsmashbox#1%
+% {\ht#1\zeropoint
+% \dp#1\zeropoint}
%D The next implementation is less sensitive for spurious spaces.
\newcount\c_boxes_register
-\protected\def\smashbox
+\permanent\protected\def\smashbox
{\afterassignment\syst_boxes_smash_boxes_register\c_boxes_register}
\def\syst_boxes_smash_boxes_register
@@ -113,20 +103,20 @@
\ht\c_boxes_register\zeropoint
\dp\c_boxes_register\zeropoint}
-\protected\def\hsmashbox
+\permanent\protected\def\hsmashbox
{\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register}
\def\syst_boxes_hsmashed_boxes_register
{\wd\c_boxes_register\zeropoint}
-\protected\def\vsmashbox
+\permanent\protected\def\vsmashbox
{\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register}
\def\syst_boxes_vsmashed_boxes_register
{\ht\c_boxes_register\zeropoint
\dp\c_boxes_register\zeropoint}
-\protected\def\smashedbox
+\permanent\protected\def\smashedbox
{\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register}
\protected\def\syst_boxes_smashed_boxes_register
@@ -135,6 +125,8 @@
\dp\c_boxes_register\zeropoint
\box\c_boxes_register}
+\let\smashboxed\smashedbox
+
%D \macros
%D {hsmash,vsmash,
%D hsmashed,vsmashed}
@@ -143,10 +135,10 @@
%D some subtle differences betreen the smash and smashed alternatives. The later
%D ones reduce all dimensions to zero.
-\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
-\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
-\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox}
-\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox}
+\permanent\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
+\permanent\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
+\permanent\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox}
+\permanent\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox}
\protected\def\syst_boxes_hsmashed_nextbox
{\wd\nextbox\zeropoint
@@ -176,8 +168,8 @@
%D \smashedvbox to ... {...}
%D \stoptyping
-\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
-\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
+\permanent\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
+\permanent\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
%D First we define a helper. We use a \LUATEX\ feature in order to avoid
%D mathpalettes.
@@ -195,7 +187,7 @@
%D catcode safer. It is needed by the math module (although the \type {\leavevmode}
%D is not added here).
-\protected\def\smash
+\permanent\protected\def\smash
{\begingroup
\futureexpandis[\syst_boxes_smash_yes\syst_boxes_smash_nop}
@@ -267,9 +259,9 @@
%D {\mathchoice}, the next macro looks ugly. We also take care of non||braced
%D arguments.
-\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
-\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
-\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h}
+\permanent\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
+\permanent\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
+\permanent\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h}
\def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make }
\def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v}
@@ -333,7 +325,7 @@
%D We also define plain's \type {\mathstrut}.
-\protected\def\mathstrut{\vphantom(} % can be made faster by inlining
+\permanent\protected\def\mathstrut{\vphantom(} % can be made faster by inlining
%D \macros
%D {getboxheight}
@@ -367,7 +359,7 @@
%D The next alternative is slightly more clever, since it accepts \type {{12}} as
%D well as \type {12} as box number.
-\protected\def\getboxheight#1\of#2\box#3%
+\permanent\protected\def\getboxheight#1\of#2\box#3%
{\def\next{#1\htdp\c_boxes_register}%
\afterassignment\next\c_boxes_register=#3}
@@ -416,7 +408,7 @@
\newcount\noflines
\newdimen\noflinesheight
-\protected\def\getnoflines#1%
+\permanent\protected\def\getnoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -432,7 +424,7 @@
\advance\noflines\minusone
\fi}
-\protected\def\getroundednoflines#1%
+\permanent\protected\def\getroundednoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -446,7 +438,7 @@
\noflines\noflinesheight
\fi}
-\protected\def\getrawnoflines#1%
+\permanent\protected\def\getrawnoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -510,11 +502,11 @@
\def\syst_boxes_determine_noflines
{\expandafter\egroup\expandafter\noflines\noflinesinbox\nextbox\relax}
-\protected\def\determinenoflines
+\permanent\protected\def\determinenoflines
{\bgroup
\forgetall
- \let\crlf\endgraf
- \let\\\endgraf
+ \enforced\let\crlf\endgraf
+ \enforced\let\\\endgraf
\dowithnextboxcs\syst_boxes_determine_noflines\vbox}
%D \macros
@@ -528,7 +520,7 @@
%D \doiftext {data} {then branch}
%D \stoptyping
-\protected\def\doifelsetext#1%
+\permanent\protected\def\doifelsetext#1%
{\begingroup
\setbox\scratchbox\hbox % no \hpack because we can have fallbacks
{\settrialtypesetting
@@ -539,7 +531,7 @@
\endgroup\expandafter\firstoftwoarguments
\fi}
-\protected\def\doiftext#1%
+\permanent\protected\def\doiftext#1%
{\begingroup
\setbox\scratchbox\hbox % no \hpack because we can have fallbacks
{\settrialtypesetting
@@ -589,7 +581,7 @@
%D In this implementation the \type {\aftergroup} construction is needed because
%D \type {\afterassignment} is executed inside the box.
-\protected\def\dowithnextbox#1%
+\permanent\protected\def\dowithnextbox#1%
{\def\syst_boxes_with_next_box{#1}%
\afterassignment\syst_boxes_with_next_box_indeed
\setbox\nextbox}
@@ -597,7 +589,7 @@
\def\syst_boxes_with_next_box_indeed
{\aftergroup\syst_boxes_with_next_box}
-\protected\def\dowithnextboxcs#1%
+\permanent\protected\def\dowithnextboxcs#1%
{\let\syst_boxes_with_next_box#1%
\afterassignment\syst_boxes_with_next_box_indeed
\setbox\nextbox}
@@ -642,12 +634,12 @@
%D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing
%D parameters.
-\def\nextboxht {\ht\nextbox}
-\def\nextboxwd {\wd\nextbox}
-\def\nextboxdp {\dp\nextbox}
-\def\nextboxhtdp{\htdp\nextbox}
+\permanent\def\nextboxht {\ht\nextbox}
+\permanent\def\nextboxwd {\wd\nextbox}
+\permanent\def\nextboxdp {\dp\nextbox}
+\permanent\def\nextboxhtdp{\htdp\nextbox}
-\protected\def\flushnextbox{\box\nextbox}
+\permanent\protected\def\flushnextbox{\box\nextbox}
%D \macros
%D {dowithnextboxcontent}
@@ -661,16 +653,24 @@
%D
%D {\em todo: Search source for potential usage!}
-\protected\def\dowithnextboxcontent#1#2% inside, after
- {\def\syst_boxes_with_next_box_one{#2}%
- \def\syst_boxes_with_next_box_two{#1}%
- \afterassignment\syst_boxes_with_next_box_content_indeed
+% \protected\def\dowithnextboxcontent#1#2% inside, after
+% {\def\syst_boxes_with_next_box_one{#2}%
+% \def\syst_boxes_with_next_box_two{#1}%
+% \afterassignment\syst_boxes_with_next_box_content_indeed
+% \setbox\nextbox}
+%
+% \protected\def\dowithnextboxcontentcs#1#2% inside, after
+% {\let\syst_boxes_with_next_box_one#2%
+% \let\syst_boxes_with_next_box_two#1%
+% \afterassignment\syst_boxes_with_next_box_content_indeed
+% \setbox\nextbox}
+
+\permanent\unexpanded\def\dowithnextboxcontent#1#2% inside, after
+ {\afterassigned{#1\aftergrouped{#2}}%
\setbox\nextbox}
-\protected\def\dowithnextboxcontentcs#1#2% inside, after
- {\let\syst_boxes_with_next_box_one#2%
- \let\syst_boxes_with_next_box_two#1%
- \afterassignment\syst_boxes_with_next_box_content_indeed
+\permanent\unexpanded\def\dowithnextboxcontentcs#1#2% inside, after
+ {\afterassigned{#1\aftergroup#2}%
\setbox\nextbox}
\def\syst_boxes_with_next_box_content_indeed
@@ -682,27 +682,28 @@
%D Some well known friends, but we implement them our own way. We want the macros to
%D work in both math and text mode.
-\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup}
-\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup}
-\def\dodoclap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup}
-
-\def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox}
-\def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox}
-\def\doclap{\begingroup\dowithnextboxcs\dodoclap\hbox}
-
-\def\domathclap{\mathpalette\dodomathclap} \def\dodomathclap#1#2{\doclap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
-\def\domathllap{\mathpalette\dodomathllap} \def\dodomathllap#1#2{\dollap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
-\def\domathrlap{\mathpalette\dodomathrlap} \def\dodomathrlap#1#2{\dorlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
-
-\protected\def\rlap{\mathortext\domathrlap\dorlap}
-\protected\def\llap{\mathortext\domathllap\dollap}
-\protected\def\clap{\mathortext\domathclap\doclap}
-
-\def\dodotlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup}
-\def\dodoblap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup}
-
-\protected\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
-\protected\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
+\def\syst_boxes_do_rlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup}
+\def\syst_boxes_do_llap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup}
+\def\syst_boxes_do_clap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup}
+\def\syst_boxes_do_tlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup}
+\def\syst_boxes_do_blap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup}
+
+\def\syst_boxes_rlap {\begingroup\dowithnextboxcs\syst_boxes_do_rlap\hbox}
+\def\syst_boxes_llap {\begingroup\dowithnextboxcs\syst_boxes_do_llap\hbox}
+\def\syst_boxes_clap {\begingroup\dowithnextboxcs\syst_boxes_do_clap\hbox}
+\def\syst_boxes_math_clap{\mathpalette\syst_boxes_do_math_clap}
+\def\syst_boxes_math_llap{\mathpalette\syst_boxes_do_math_llap}
+\def\syst_boxes_math_rlap{\mathpalette\syst_boxes_do_math_rlap}
+
+\def\syst_boxes_do_math_clap#1#2{\syst_boxes_clap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\syst_boxes_do_math_llap#1#2{\syst_boxes_llap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+\def\syst_boxes_do_math_rlap#1#2{\syst_boxes_rlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}}
+
+\permanent\protected\def\rlap{\mathortext\syst_boxes_math_rlap\syst_boxes_rlap}
+\permanent\protected\def\llap{\mathortext\syst_boxes_math_llap\syst_boxes_llap}
+\permanent\protected\def\clap{\mathortext\syst_boxes_math_clap\syst_boxes_clap}
+\permanent\protected\def\tlap{\begingroup\dowithnextboxcs\syst_boxes_do_tlap\vbox}
+\permanent\protected\def\blap{\begingroup\dowithnextboxcs\syst_boxes_do_blap\vbox}
%D \macros
%D {beginofshapebox,
@@ -816,6 +817,10 @@
%D bad spacing. This means that for instance linenumbers etc. should be given zero
%D height and depth before being lapped into the margin. The previous examples
%D ignore this side effect, but beware!
+%D
+%D This is ancient stuff and proably not used any more but we keep it around or
+%D maybe turn it into a module some day. It shows the kind of struggling that we
+%D needed before \LUATEX\ came around.
\newif \ifsomeshapeleft
\newif \ifreshapingbox
@@ -836,7 +841,7 @@
\def\shapesignal{.12345678pt} % or 12345sp
-\protected\def\reshapebox#1%
+\permanent\protected\def\reshapebox#1%
{\doreshapebox
{#1}%
{\penalty\shapepenalty}%
@@ -860,14 +865,14 @@
% We will turn this into a \MKIV\ variant (we can use \type {\vpack} too).
-\protected\def\insertshapesignal
+\permanent\protected\def\insertshapesignal
{\hpack to \shapesignal{\strut\hss}% plus \strut
\prevdepth\strutdp} % never \nointerlineskip
-\protected\def\restoreshapebox % compensates for the signal
+\permanent\protected\def\restoreshapebox % compensates for the signal
{\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}}
-\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
+\permanent\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
{\ifnum\lastnodetype=\gluenodecode
\shapeskip\lastskip
\global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}%
@@ -901,21 +906,21 @@
\advance\shapecounter \plusone
\fi}
-\protected\def\beginofshapebox
+\permanent\protected\def\beginofshapebox
{\setbox\oldshapebox\vbox
\bgroup
\reshapingboxtrue
\the\everyshapebox
\insertshapesignal}
-\protected\def\endofshapebox
+\permanent\protected\def\endofshapebox
{\endgraf
\egroup}
\let\beginshapebox\beginofshapebox
\let\endshapebox \endofshapebox
-\protected\def\flushshapebox
+\permanent\protected\def\flushshapebox
{\bgroup
\ifzeropt\ht\newshapebox
\else
@@ -966,7 +971,7 @@
%
% \omlijnd[offset=0pt,hoogte=8mm,uitlijnen={rechts,laho}]{\bfa test}
-\protected\def\innerflushshapebox
+\permanent\protected\def\innerflushshapebox
{\ifzeropt\ht\newshapebox \else
\unvcopy\newshapebox\relax % unvcopy ! else spacing problem
% \kern-\dp\newshapebox\relax
@@ -989,7 +994,7 @@
%D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and
%D depth of the line.
-\protected\def\shapedhbox % lines with non strutted dimensions have
+\permanent\protected\def\shapedhbox % lines with non strutted dimensions have
{\expanded{\dowithnextbox % interlineskip so if we want the original
{\ht\nextbox\the\ht\shapebox % spacing, we need to preserve the original
\dp\nextbox\the\dp\shapebox % height and depth which is definitely
@@ -1009,10 +1014,10 @@
%D \showhyphens{dohyphenatedword}
%D \stoptyping
-\protected\def\doshowhyphenatednextbox
+\permanent\protected\def\doshowhyphenatednextbox
{\clf_showhyphenatedinlist\nextbox}
-\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua)
+\permanent\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua)
{\dowithnextboxcs\doshowhyphenatednextbox\hpack}
%D The following macros are seldom used but handy for tracing.
@@ -1023,19 +1028,13 @@
%D \hyphenatedfile{tufte}
%D \stoptyping
-\protected\def\dohyphenatednextbox
- {\clf_hyphenatedlist\nextbox false\relax
- \unhbox\nextbox}
-
-\protected\def\hyphenatedword {\dowithnextboxcs\dohyphenatednextbox\hbox}
-\protected\def\hyphenatedpar {\dowithnextboxcs\dohyphenatednextbox\hbox}
-\protected\def\hyphenatedfile#1{\dowithnextboxcs\dohyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}}
+\def\syst_boxes_hyphenatednextbox {\clf_hyphenatedlist\nextbox false\relax\unhbox\nextbox}
+\def\syst_boxes_hyphenatednextboxcolor{\clf_hyphenatedlist\nextbox true \relax\unhbox\nextbox}
-\protected\def\dohyphenatednextboxcolor
- {\clf_hyphenatedlist\nextbox true\relax
- \unhbox\nextbox}
-
-\protected\def\hyphenatedcoloredword{\dowithnextboxcs\dohyphenatednextboxcolor\hbox}
+\permanent\protected\def\hyphenatedword {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox}
+\permanent\protected\def\hyphenatedpar {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox}
+\permanent\protected\def\hyphenatedfile #1{\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}}
+\permanent\protected\def\hyphenatedcoloredword{\dowithnextboxcs\syst_boxes_hyphenatednextboxcolor\hbox}
%D \macros
%D {processtokens}
@@ -1064,34 +1063,36 @@
%D The list of tokens may contain spaces, while \type {\\}, \type {{}} and \type {\
%D } are handled as space too.
-\protected\def\processtokens#1#2#3#4#5%
+%D This can be done in a more modern way but for nostalgic reasons we keep it.
+
+\permanent\protected\def\processtokens#1#2#3#4#5%
{\begingroup
\def\lastcharacter{\lastcharacter}% hm, recursive ?
- \def\space{ }%
- \let\\=\space
+ \enforced\permanent\def\space{ }%
+ \enforced\let\\\space
\def\before {#1}%
\def\between{#2}%
\def\after {#3}%
\def\white {#4}%
\let\savedbefore\before
- \doprocesstokens#5\lastcharacter
+ \syst_boxes_processtokens#5\lastcharacter
\endgroup}
-\def\doprocesstokens% the space after = is essential
- {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= }
+\def\syst_boxes_processtokens% the space after = is essential
+ {\afterassignment\syst_boxes_do_processtokens\let\nextprocessedtoken= }
-\def\redoprocessedtoken
+\def\syst_boxes_redo_processedtoken
{\dowithnextbox
{\before{\copy\nextbox}% \before can use nextbox several times
\let\before\between
- \doprocesstokens}
+ \syst_boxes_processtokens}
\hbox\bgroup}
-\def\dodoprocesstokens
+\def\syst_boxes_do_processtokens
{\ifx\nextprocessedtoken\lastcharacter
\after
\orelse\ifx\nextprocessedtoken\bgroup
- \expandafter\redoprocessedtoken
+ \expandafter\syst_boxes_redo_processedtoken
\else
\expandafter\if\space\nextprocessedtoken
\after\white
@@ -1100,7 +1101,7 @@
\before\nextprocessedtoken
\let\before\between
\fi
- \expandafter\doprocesstokens
+ \expandafter\syst_boxes_processtokens
\fi}
%D \macros
@@ -1118,20 +1119,22 @@
%D
%D When calculating the room needed, we take the width of the third argument into
%D account, which leads to a bit more complex macro than needed at first sight.
+%D
+%D Sort of obsolete I guess:
-\def\dodoboundtext#1%
+\def\syst_boxes_boundtext#1%
{\setbox\scratchboxone\hbox{#1}%
\advance\scratchdimen -\wd\scratchboxone
\ifdim\scratchdimen>\zeropoint\relax#1\fi}
-\def\doboundtext#1#2#3% still used?
+\permanent\protected\def\doboundtext#1#2#3% still used?
{\hbox
{\setbox\scratchbox\hbox{#1}%
\scratchdimen#2\relax
\ifdim\wd\scratchbox>\scratchdimen
\setbox\scratchbox\hbox{#3}%
\advance\scratchdimen -\wd\scratchbox
- \handletokens#1\with\dodoboundtext
+ \handletokens#1\with\syst_boxes_boundtext
\fi
\box\scratchbox}}
@@ -1155,7 +1158,7 @@
%D See \MKIV\ file for the older implementation.
-\protected\def\limitatetext#1#2#3%
+\permanent\protected\def\limitatetext#1#2#3%
{\splitatcomma{#2}\leftlimit\rightlimit
\limitated
left \leftlimit
@@ -1173,7 +1176,7 @@
%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown}
%D \stoptyping
-\protected\def\limitatefirstline#1#2#3%
+\permanent\protected\def\limitatefirstline#1#2#3%
{\hbox\bgroup\strut % \hpack
\setbox\scratchbox\hbox{\begstrut#1\endstrut}%
\ifdim\wd\scratchbox>#2\relax
@@ -1216,7 +1219,7 @@
% todo: provide variant with #1 picked up as box
-\protected\def\processisolatedchars#1#2%
+\permanent\protected\def\processisolatedchars#1#2%
{\dontleavehmode
\begingroup
\setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
@@ -1229,7 +1232,7 @@
\relax
\endgroup}
-\protected\def\processisolatedwords#1#2%
+\permanent\protected\def\processisolatedwords#1#2%
{\dontleavehmode
\begingroup
\setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
@@ -1244,7 +1247,7 @@
%D A variant:
-\protected\def\applytocharacters#1%
+\permanent\protected\def\applytocharacters#1%
{\dontleavehmode
\dowithnextbox{\clf_applytobox
method {char}%
@@ -1254,7 +1257,7 @@
\relax}%
\hbox}
-\protected\def\applytowords#1%
+\permanent\protected\def\applytowords#1%
{\dontleavehmode
\dowithnextbox{\clf_applytobox
method {word}%
@@ -1266,33 +1269,33 @@
%D The old call:
-\protected\def\processwords#1%
+\permanent\protected\def\processwords#1%
{\processisolatedwords{#1}\processword}
\let\processword\relax
-\protected\def\applytosplitstringchar#1#2%
+\permanent\protected\def\applytosplitstringchar#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
method {char}%
\relax}
-\protected\def\applytosplitstringword#1#2%
+\permanent\protected\def\applytosplitstringword#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
method {word}%
\relax}
-\protected\def\applytosplitstringline#1#2%
+\permanent\protected\def\applytosplitstringline#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
method {line}%
\relax}
-\protected\def\applytosplitstringcharspaced#1#2%
+\permanent\protected\def\applytosplitstringcharspaced#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
@@ -1300,7 +1303,7 @@
spaced true%
\relax}
-\protected\def\applytosplitstringwordspaced#1#2%
+\permanent\protected\def\applytosplitstringwordspaced#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
@@ -1308,7 +1311,7 @@
spaced true%
\relax}
-\protected\def\applytosplitstringlinespaced#1#2%
+\permanent\protected\def\applytosplitstringlinespaced#1#2%
{\dontleavehmode\clf_processsplit
data {#2}%
command {\csstring#1}%
@@ -1341,11 +1344,11 @@
%D would have ended up in the text. This macro can be useful when building
%D complicated menus, headers and footers and|/|or margin material.
-\protected\def\sbox
+\permanent\protected\def\sbox
{\vpack\bgroup
\dowithnextboxcs\syst_boxes_sbox_finish\vbox}
-\protected\def\syst_boxes_sbox_finish
+\def\syst_boxes_sbox_finish
{\boxyoffset\nextbox-\strutdp
\dp\nextbox\strutdp
\ht\nextbox\strutht
@@ -1358,11 +1361,11 @@
%D xx \ruledhbox{\inlinedbox{\tfd test}} xx
%D \stoptyping
-\protected\def\inlinedbox
+\permanent\protected\def\inlinedbox
{\bgroup
\dowithnextboxcs\syst_boxes_inlined_finish\hbox}
-\protected\def\syst_boxes_inlined_finish
+\def\syst_boxes_inlined_finish
{\boxyoffset\nextbox-\dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax
\ht\nextbox\strutht
\dp\nextbox\strutdp
@@ -1374,7 +1377,7 @@
%D
%D This boxing macro limits the height and depth to those of a strut.
-\protected\def\struttedbox
+\permanent\protected\def\struttedbox
{\hpack\bgroup
\dowithnextboxcs\syst_boxes_struttedbox_finish\hbox}
@@ -1390,7 +1393,7 @@
%D This macro compensates the difference between the topskip and strutheight. Watch
%D how we preserve the depth when it equals strutdepth.
-\protected\def\topskippedbox
+\permanent\protected\def\topskippedbox
{\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
\def\syst_boxes_topskippedbox_finish
@@ -1442,7 +1445,7 @@
%D The dimensions of the surrounding box are kept intact. This commands handles
%D positive and negative dimensions (which is why we need two boxes with rules).
-\protected\def\centeredbox#1#% height +/-dimen width +/-dimen
+\permanent\protected\def\centeredbox#1#% height +/-dimen width +/-dimen
{\bgroup
\dontcomplain
\forgetall
@@ -1479,7 +1482,7 @@
%D
%D Do you see why we call this one \type {next}?
-\protected\def\centerednextbox#1#%
+\permanent\protected\def\centerednextbox#1#%
{\bgroup
\dowithnextbox
{\hsize\wd\nextbox
@@ -1500,7 +1503,7 @@
%D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local
%D dimensions are supported.
-\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen
+\permanent\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen
{\bgroup
\dowithnextbox
{\setlocalhsize
@@ -1530,7 +1533,7 @@
\newif\ifstretchrigidcolumns
\newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections
-\protected\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
+\permanent\protected\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
{\xdef\savedrigidhsize{\the\hsize}%
\hsize#1\relax
\global\chardef\rigidcolumns#3\relax
@@ -1551,7 +1554,7 @@
\let\rigidcolumnlines\!!zerocount
-\protected\def\rigidcolumnbalance#1%
+\permanent\protected\def\rigidcolumnbalance#1%
{\ifnum\rigidcolumns=1 % tzt ook h/d correctie
\ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax
\else
@@ -1676,17 +1679,17 @@
%newbox\d_syst_boxes_vboxtohbox
\newbox\d_syst_boxes_separator
-\protected\def\startvboxtohboxseparator
+\permanent\protected\def\startvboxtohboxseparator
{\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup}
-\protected\def\stopvboxtohboxseparator
+\permanent\protected\def\stopvboxtohboxseparator
{\egroup}
-\protected\def\startvboxtohbox
+\permanent\protected\def\startvboxtohbox
{\begingroup
\setbox\scratchbox\hbox\bgroup}
-\protected\def\stopvboxtohbox
+\permanent\protected\def\stopvboxtohbox
{\ifvoid\d_syst_boxes_separator
\hskip\zeropoint\ifcase\vboxtohboxslack\else\s!minus\vboxtohboxslack\fi % we really need a skip
\else
@@ -1699,12 +1702,12 @@
% A possible reconstruction:
-\protected\def\convertvboxtohbox
+\permanent\protected\def\convertvboxtohbox
{\makehboxofhboxes
\setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack
\noindent\unhbox\scratchboxone\par}
-\protected\def\makehboxofhboxes
+\permanent\protected\def\makehboxofhboxes
{\setbox\scratchboxone\emptyhbox
\loop % \doloop { .. \exitloop .. }
\setbox\scratchboxtwo\lastbox
@@ -1712,7 +1715,7 @@
\setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}%
\repeat}
-\protected\def\removehboxes
+\permanent\protected\def\removehboxes
{\setbox\scratchboxone\lastbox
\ifhbox\scratchboxone
{\removehboxes}\unhbox\scratchboxone
@@ -1720,11 +1723,11 @@
% And one special for notes:
-\protected\def\starthboxestohbox
+\permanent\protected\def\starthboxestohbox
{\bgroup
\setbox\scratchbox\vbox\bgroup}
-\protected\def\stophboxestohbox
+\permanent\protected\def\stophboxestohbox
{\egroup
\clf_vboxlisttohbox\scratchbox\nextbox\dimexpr\hboxestohboxslack\relax
\dontleavehmode
@@ -1744,7 +1747,7 @@
\newdimen \lasthhboxwidth
\newskip \hhboxindent
-\protected\def\unhhbox#1\with#2%
+\permanent\protected\def\unhhbox#1\with#2%
{\bgroup
\nopenalties
\dontcomplain
@@ -1770,14 +1773,14 @@
\fi}%
\egroup}
-\def\dohboxofvbox
+\def\syst_boxes_hboxofvbox
{\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}%
\unhbox1
\egroup}
-\protected\def\hboxofvbox
+\permanent\protected\def\hboxofvbox
{\bgroup
- \afterassignment\dohboxofvbox
+ \afterassignment\syst_boxes_hboxofvbox
\scratchcounter=}
%D This macro can be used to break a paragraph apart and treat each line seperately,
@@ -1818,7 +1821,7 @@
%D dimension of this box suggest some content, the resulting box is unboxed and
%D surrounded by the first two arguments, else the third arguments is executed.
-\protected\def\doifcontent#1#2#3%
+\permanent\protected\def\doifcontent#1#2#3%
{\dowithnextbox
{\ifhbox\nextbox
\ifdim\wd\nextbox>\zeropoint
@@ -1861,7 +1864,7 @@
\newbox\processbox % public : this is the one where \nextbox's end up in
-\protected\def\processboxes#1%
+\permanent\protected\def\processboxes#1%
{\bgroup
\def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
\setbox\processbox\emptybox
@@ -1899,7 +1902,7 @@
%D
%D \leavevmode\getbuffer
-\def\boxisempty#1%
+\permanent\def\boxisempty#1%
{\ifdim\wd#1=\zeropoint
\ifdim\ht#1=\zeropoint
\ifdim\dp#1=\zeropoint
@@ -1935,7 +1938,7 @@
\kern-\scratchwidth
\hpack to \scratchwidth{\hss\box\nextbox \hss}}}
-\protected\def\startoverlay
+\permanent\protected\def\startoverlay
{\bgroup
\let\stopoverlay\egroup
\processboxes\syst_boxes_overlay_process}
@@ -1953,7 +1956,7 @@
%D
%D returns an empty box with the dimensions of the box specified, here being zero.
-\protected\def\fakebox
+\permanent\protected\def\fakebox
{\bgroup
\afterassignment\syst_boxes_fakebox_finish\scratchcounter}
@@ -1980,15 +1983,20 @@
%D \type {to 3cm}, but align to the left, middle and right. These box types can be
%D used to typeset paragraphs.
-\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next}
+\def\syst_boxes_lrc_process#1%
+ {\bgroup
+ \forgetall
+ \enforced\let\\\endgraf
+ #1%
+ \let\nexttoken}
-\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft }
-\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
-\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
+\permanent\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft }
+\permanent\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
+\permanent\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
-\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft }
-\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter}
-\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright }
+\permanent\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft }
+\permanent\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter}
+\permanent\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright }
%D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align
%D boxes, like in:
@@ -2010,8 +2018,8 @@
%D
%D \getbuffer
-\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
-\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
+\permanent\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
+\permanent\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
\def\syst_boxes_tbox_finish
{\scratchheight\ht\strutbox
@@ -2036,13 +2044,13 @@
%D
%D A few more boxes.
-\def\dodolhbox{\hpack to \hsize{\box\nextbox\hss }}
-\def\dodomhbox{\hpack to \hsize{\hss\box\nextbox\hss}}
-\def\dodorhbox{\hpack to \hsize{\hss\box\nextbox }}
+\def\syst_boxes_lhbox{\hpack to \hsize{\box\nextbox\hss }}
+\def\syst_boxes_mhbox{\hpack to \hsize{\hss\box\nextbox\hss}}
+\def\syst_boxes_rhbox{\hpack to \hsize{\hss\box\nextbox }}
-\protected\def\lhbox{\dowithnextboxcs\dodolhbox\hbox}
-\protected\def\mhbox{\dowithnextboxcs\dodomhbox\hbox}
-\protected\def\rhbox{\dowithnextboxcs\dodorhbox\hbox}
+\permanent\protected\def\lhbox{\dowithnextboxcs\syst_boxes_lhbox\hbox}
+\permanent\protected\def\mhbox{\dowithnextboxcs\syst_boxes_mhbox\hbox}
+\permanent\protected\def\rhbox{\dowithnextboxcs\syst_boxes_rhbox\hbox}
\let\lefthbox \lhbox
\let\midhbox \mhbox
@@ -2063,15 +2071,15 @@
\newdimen\sizeofbox
-\protected\def\boxofsize#1%
+\permanent\protected\def\boxofsize#1%
{\bgroup
\sizeofbox\zeropoint
\scratchdimen\zeropoint
\def\docommand
{\advance\sizeofbox\scratchdimen
- \futurelet\next\dodocommand}%
+ \futurelet\nexttoken\dodocommand}%
\def\dodocommand
- {\ifx\next\bgroup
+ {\ifx\nexttoken\bgroup
\expanded{\egroup#1 to \the\sizeofbox}%
\else
\expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen
@@ -2085,7 +2093,7 @@
% \limitvbox
% \limithbox
-\protected\def\limitatelines#1#2% size sentinel
+\permanent\protected\def\limitatelines#1#2% size sentinel
{\dowithnextbox
{\scratchdimen#1\hsize
\ifdim\wd\nextbox>\scratchdimen
@@ -2096,7 +2104,7 @@
\unhbox\nextbox}
\hbox}
-\protected\def\fittoptobaselinegrid % weg hier
+\permanent\protected\def\fittoptobaselinegrid % weg hier
{\dowithnextbox
{\bgroup
\par
@@ -2125,7 +2133,7 @@
\setbox\fakedboxcursor\hpack
{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
-\protected\def\boxcursor % overloaded in core-vis
+\permanent\protected\def\boxcursor % overloaded in core-vis
{\iftraceboxplacement
\bgroup
\scratchdimen2\onepoint
@@ -2142,21 +2150,21 @@
\copy\fakedboxcursor
\fi}
-\protected\def\placedbox
+\permanent\protected\def\placedbox
{\iftraceboxplacement\ruledhbox\else\hbox\fi}
\newdimen\boxoffset
\newdimen\boxhdisplacement
\newdimen\boxvdisplacement
-\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox}
-\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox}
-\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox}
-\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox}
-\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox}
-\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox}
-\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
-\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
+\permanent\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox}
+\permanent\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox}
+\permanent\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox}
+\permanent\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox}
+\permanent\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox}
+\permanent\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox}
+\permanent\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
+\permanent\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
\let\topleftbox \lefttopbox
\let\toprightbox \righttopbox
@@ -2235,10 +2243,10 @@
\box\nextbox
\egroup}
-\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox}
-\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
-\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox}
-\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
+\permanent\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox}
+\permanent\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
+\permanent\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox}
+\permanent\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
\def\syst_boxes_middlebox_finish
{\global\boxhdisplacement-.5\wd\nextbox
@@ -2281,7 +2289,7 @@
%D
%D Experimental, not yet frozen:
-\protected\def\lrtbbox#1#2#3#4% l r t b
+\permanent\protected\def\lrtbbox#1#2#3#4% l r t b
{\bgroup
\dowithnextboxcontent
{\advance\hsize-#1\advance\hsize-#2\relax
@@ -2294,7 +2302,7 @@
%D
%D See core-tbl.tex for an example of its usage:
-\protected\def\toplinebox
+\permanent\protected\def\toplinebox
{\dowithnextboxcs\syst_boxes_toplinebox_finish\tbox}
\def\syst_boxes_toplinebox_finish
@@ -2333,20 +2341,20 @@
\installcorenamespace {stackbox}
\installcorenamespace {stacklst}
-\protected\def\setstackbox#1#2%
+\permanent\protected\def\setstackbox#1#2%
{\ifcsname\??stackbox#1:#2\endcsname\else
\expandafter\newbox\csname\??stackbox#1:#2\endcsname
\fi
\global\setbox\csname\??stackbox#1:#2\endcsname\vbox}
-\protected\def\initializeboxstack#1%
+\permanent\protected\def\initializeboxstack#1%
{\def\docommand##1{\setstackbox{#1}{##1}{}}%
\ifcsname\??stacklst#1\endcsname
\expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand
\fi
\letgvalueempty{\??stacklst#1}}
-\protected\def\savebox#1#2% stack name
+\permanent\protected\def\savebox#1#2% stack name
{% beware, \setxvalue defines the cs beforehand so we cannot use the
% test inside the { }
\ifcsname\??stacklst#1\endcsname
@@ -2357,27 +2365,27 @@
\fi
\setstackbox{#1}{#2}}
-\protected\def\flushbox#1#2% unwrapped
+\permanent\protected\def\flushbox#1#2% unwrapped
{\ifcsname\??stackbox#1:#2\endcsname
\box\lastnamedcs
\else
\emptybox
\fi}
-\protected\def\restorebox#1#2% unwrapped
+\permanent\protected\def\restorebox#1#2% unwrapped
{\ifcsname\??stackbox#1:#2\endcsname
\copy\lastnamedcs
\else
\emptybox
\fi}
-\protected\def\foundbox#1#2% wrapped
+\permanent\protected\def\foundbox#1#2% wrapped
{\vpack
{\ifcsname\??stackbox#1:#2\endcsname
\copy\lastnamedcs
\fi}}
-\protected\def\doifelsebox#1#2%
+\permanent\protected\def\doifelsebox#1#2%
{\ifcsname\??stackbox#1:#2\endcsname
\ifvoid\lastnamedcs
\doubleexpandafter\secondoftwoarguments
@@ -2395,7 +2403,8 @@
\installcorenamespace {boxstack}
\newcount\c_syst_boxes_stack
-\let \b_syst_boxes_stack\relax
+
+\mutable\let\b_syst_boxes_stack\relax
\protected\def\syst_boxes_stack_allocate
{\newbox\b_syst_boxes_stack
@@ -2413,11 +2422,11 @@
{#1\setbox#2\box\csname\??boxstack\number\c_syst_boxes_stack\endcsname
\global\advance\c_syst_boxes_stack\minusone}
-\protected\def\localpushbox {\syst_boxes_push\relax}
-\protected\def\localpopbox {\syst_boxes_pop \relax}
+\permanent\protected\def\localpushbox {\syst_boxes_push\relax}
+\permanent\protected\def\localpopbox {\syst_boxes_pop \relax}
-\protected\def\globalpushbox{\syst_boxes_push\global}
-\protected\def\globalpopbox {\syst_boxes_pop \global}
+\permanent\protected\def\globalpushbox{\syst_boxes_push\global}
+\permanent\protected\def\globalpopbox {\syst_boxes_pop \global}
%D And here is a more modern one (not yet in i-*):
%D
@@ -2435,15 +2444,15 @@
%D \resetboxesincache{foo}
%D \stoptyping
-\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax}
-\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax}
-\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}}
-\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax}
-\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}}
-\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}}
-\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}}
+\permanent\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax}
+\permanent\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax}
+\permanent\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}}
+\permanent\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax}
+\permanent\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}}
+\permanent\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}}
+\permanent\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}}
-\protected\def\putnextboxincache#1#2%
+\permanent\protected\def\putnextboxincache#1#2%
{\dowithnextbox{\putboxincache{#1}{#2}\nextbox}}
%D \macros
@@ -2452,21 +2461,21 @@
%D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes
%D sure we have depth. Both macros leave the \type {\prevdepth} untouched.
-\protected\def\removedepth
+\permanent\protected\def\removedepth
{\ifvmode
\ifdim\prevdepth>\zeropoint
\kern-\prevdepth
\fi
\fi}
-\protected\def\obeydepth
+\permanent\protected\def\obeydepth
{\par % watch out for changes in math formulas
\ifvmode\ifdim\prevdepth<\zeropoint\orelse\ifdim\prevdepth<\strutdp
\kern\dimexpr\strutdp-\prevdepth\relax
\prevdepth\strutdp
\fi\fi}
-\protected\def\undepthed
+\permanent\protected\def\undepthed
{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\hbox}
%D \macros
@@ -2474,10 +2483,10 @@
%D
%D A funny (but rather stupid) one, plus a redefinition.
-\protected\def\removebottomthings
+\permanent\protected\def\removebottomthings
{\dorecurse\plusfive{\unskip\unkern\unpenalty}}
-\protected\def\removelastskip % \ifvmode the plain tex one \fi
+\permanent\protected\def\removelastskip % \ifvmode the plain tex one \fi, overloaded to \permanent in spac-ver
{\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
%D \macros
@@ -2486,7 +2495,7 @@
%D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so
%D it will go away.
-\protected\def\makestrutofbox % not used
+\permanent\protected\def\makestrutofbox % not used
{\afterassignment\syst_boxes_makestrutofbox\c_boxes_register}
\def\syst_boxes_makestrutofbox
@@ -2505,8 +2514,8 @@
%D \hsmash{\raisebox{100pt}\hbox{test}}
%D \stoptyping
-\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
-\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+\permanent\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+\permanent\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
\def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish}
\def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish}
@@ -2527,7 +2536,7 @@
% vcenter in text, we kunnen vcenter overloaden
-\protected\def\halfwaybox
+\permanent\protected\def\halfwaybox
{\hpack\bgroup
\dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox}
@@ -2536,7 +2545,7 @@
\lower.5\ht\nextbox\box\nextbox
\egroup}
-\protected\def\depthonlybox
+\permanent\protected\def\depthonlybox
{\tpack\bgroup
\dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox}
@@ -2547,8 +2556,8 @@
%D New:
-\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi}
-\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi}
+\permanent\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi}
+\permanent\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi}
%D And even rawer:
@@ -2561,7 +2570,7 @@
%D
%D A not so well unhboxable box can be made with:
-\protected\def\frozenhbox
+\permanent\protected\def\frozenhbox
{\hpack\bgroup
\dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
@@ -2577,19 +2586,17 @@
\installcorenamespace {box_x}
\installcorenamespace {box_y}
-\protected\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
-\protected\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+\permanent\protected\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\permanent\protected\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
-\protected\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
-\protected\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
+\permanent\protected\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
+\permanent\protected\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
-%def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi}
-%def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi}
-\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
-\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\permanent\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\permanent\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
-\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence
-\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence
+\permanent\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence
+\permanent\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence
%D \macros
%D {shownextbox}
@@ -2604,7 +2611,7 @@
%D \shownextbox\vbox{\setupwhitespace[big]test\endgraf\thinrule}
%D \stoptyping
-\protected\def\shownextbox % seldom used
+\permanent\protected\def\shownextbox % seldom used
{\dowithnextbox
{\bgroup
\showboxbreadth\maxdimen
@@ -2616,7 +2623,7 @@
\interactionmode\scratchcounter
\egroup}}
-\protected\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
+\permanent\protected\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
{\bgroup
\ifhbox#1\relax
\setbox\scratchboxtwo\emptybox
@@ -2648,7 +2655,7 @@
%D \minimalhbox 100pt {test}
%D \stoptyping
-\protected\def\minimalhbox#1#%
+\permanent\protected\def\minimalhbox#1#%
{\dowithnextbox
{\bgroup
\setbox\scratchbox\hpack#1{\hss}%
@@ -2659,7 +2666,7 @@
%D A bit dirty:
-\protected\def\nodestostring#1#2% more tolerant for #2=\cs
+\permanent\protected\def\nodestostring#1#2% more tolerant for #2=\cs
{\begingroup
\setbox\nextbox\hbox{#2}%
\normalexpanded{\endgroup\edef\noexpand#1{\clf_boxtostring\nextbox}}}
@@ -2690,7 +2697,7 @@
\let\getnaturalwd\clf_getnaturalwd % no intermediate
\let\setnaturalwd\clf_setnaturalwd % no intermediate
-\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox}
+\permanent\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox}
\let\doifrighttoleftinboxelse\doifelserighttoleftinbox
@@ -2698,24 +2705,23 @@
\definesystemattribute [runningtext] [public]
-%unexpanded\def\runninghbox{\hbox attr \runningtextattribute \plusone} % not yet in i-*
-\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-*
+\permanent\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-*
%D To complement lua (yet undocumented):
-\protected\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup
-\protected\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup
-\protected\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup
+\permanent\protected\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup
+\permanent\protected\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup
+\permanent\protected\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup
-\protected\def\sethboxregister#1{\setbox#1\hbox}
-\protected\def\setvboxregister#1{\setbox#1\vbox}
-\protected\def\setvtopregister#1{\setbox#1\vtop}
+\permanent\protected\def\sethboxregister#1{\setbox#1\hbox}
+\permanent\protected\def\setvboxregister#1{\setbox#1\vbox}
+\permanent\protected\def\setvtopregister#1{\setbox#1\vtop}
-\protected\def\flushboxregister#1{\box\numexpr#1\relax}
+\permanent\protected\def\flushboxregister#1{\box\numexpr#1\relax}
-\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup
-\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup
-\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup
+\permanent\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup
+\permanent\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup
+\permanent\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup
%D For whatever third party package needs it:
%D
@@ -2731,7 +2737,7 @@
\installcorenamespace{localbox}
-\protected\def\newlocalbox#1%
+\permanent\protected\def\newlocalbox#1%
{\expandafter\let\expandafter#1\csname\??localbox\string#1\endcsname
\ifx#1\relax
\syst_aux_new_localbox#1%
@@ -2743,7 +2749,7 @@
%D Who knows when this comes in handy:
-\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax}
+\permanent\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax}
%D Keep as reference:
@@ -2753,11 +2759,11 @@
%D This one keeps dimensions and sets the shift field (and so it's more for testing
%D than for real usage):
-\protected\def\shiftbox {\clf_shiftbox}
-\protected\def\vpackbox {\clf_vpackbox}
-\protected\def\hpackbox {\clf_hpackbox}
-\protected\def\vpackedbox{\clf_vpackedbox}
-\protected\def\hpackedbox{\clf_hpackedbox}
+\permanent\protected\def\shiftbox {\clf_shiftbox}
+\permanent\protected\def\vpackbox {\clf_vpackbox}
+\permanent\protected\def\hpackbox {\clf_hpackbox}
+\permanent\protected\def\vpackedbox{\clf_vpackedbox}
+\permanent\protected\def\hpackedbox{\clf_hpackedbox}
%D This one has been moved from a 2 decade old file. It makes something boxed
%D sit on the baseline.
@@ -2772,7 +2778,6 @@
\egroup}
\hbox}
-
%D \macros
%D {widthuptohere}
%D
@@ -2784,9 +2789,9 @@
%D \stopbuffer
%D
%D \typebuffer \blank \getbuffer \blank
-
+%D
%D Implemented elsewhere:
-
+%D
%D \starttyping
%D \boxlines <box>
%D \boxline <box> <line>
@@ -2818,6 +2823,25 @@
%
% \protected\def\namedbox#1{\csname\??namedboxes#1\endcsname}
+%D Implemented elsewhere:
+%D
+%D \startbuffer
+%D \setbox0\hbox{test \footnote{test}} (\prelistbox0) (\postlistbox0)
+%D \setprelistbox0\hbox{BEFORE} \setpostlistbox0\hbox{AFTER}
+%D \box0
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+%D
+%D \starttyping
+%D \prelistbox <box>
+%D \postlistbox <box>
+%D \prelistcopy <box>
+%D \postlistcopy <box>
+%D \setprelistbox <box> <hbox|vbox|vtop|somebox>
+%D \setpostlistbox <box> <hbox|vbox|vtop|somebox>
+%D \stoptyping
+
\protect \endinput
% a bit of test code:
diff --git a/tex/context/base/mkiv/supp-ran.lua b/tex/context/base/mkiv/supp-ran.lua
index 03da4262f..7946370d7 100644
--- a/tex/context/base/mkiv/supp-ran.lua
+++ b/tex/context/base/mkiv/supp-ran.lua
@@ -53,6 +53,9 @@ end
math.setrandomseedi = setrandomseedi
local function getrandomnumber(min,max)
+ if min > max then
+ min, max = max, min
+ end
last = random(min,max)
if trace_details then
report_system("number %s",last)
diff --git a/tex/context/base/mkiv/symb-imp-cc.mkiv b/tex/context/base/mkiv/symb-imp-cc.mkiv
index e753d695f..d9f596b9c 100644
--- a/tex/context/base/mkiv/symb-imp-cc.mkiv
+++ b/tex/context/base/mkiv/symb-imp-cc.mkiv
@@ -69,8 +69,8 @@
\unexpanded\def\creativecommons#1%
{\dontleavehmode\lower.15\exheight\hbox\bgroup
- \let\inbetween\relax
- \processseparatedlist[#1][-]{\inbetween\let\inbetween\enspace\directsymbol{cc}}%
+ \overloaded\let\inbetween\relax
+ \processseparatedlist[#1][-]{\inbetween\overloaded\let\inbetween\enspace\directsymbol{cc}}%
\egroup}
\definesymbol [cc-by-sa-nc] [\creativecommons{cc-by-sa-nc}]
diff --git a/tex/context/base/mkiv/syst-aux.lmt b/tex/context/base/mkiv/syst-aux.lmt
new file mode 100644
index 000000000..c0de8a953
--- /dev/null
+++ b/tex/context/base/mkiv/syst-aux.lmt
@@ -0,0 +1,747 @@
+ if not modules then modules = { } end modules ['syst-aux'] = {
+ version = 1.001,
+ comment = "companion to syst-aux.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- slower than lpeg:
+--
+-- utfmatch(str,"(.?)(.*)$")
+-- utf.sub(str,1,1)
+
+local tonumber, next, type = tonumber, next, type
+local utfsub = utf.sub
+local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match
+local find, formatters = string.find, string.formatters
+
+local context = context
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+local setcatcode = tex.setcatcode
+local texget = tex.get
+local utf8character = lpeg.patterns.utf8character
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_set = utilities.parsers.settings_to_set
+
+local pattern = C(utf8character^-1) * C(P(1)^0)
+
+implement {
+ name = "getfirstcharacter",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ setmacro("firstcharacter",first)
+ setmacro("remainingcharacters",rest)
+ end
+}
+
+implement {
+ name = "thefirstcharacter",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ context(first)
+ end
+}
+
+implement {
+ name = "theremainingcharacters",
+ arguments = "string",
+ actions = function(str)
+ local first, rest = lpegmatch(pattern,str)
+ context(rest)
+ end
+}
+
+local pattern = C(utf8character^-1)
+local ctx_doifelse = commands.doifelse
+
+implement {
+ name = "doifelsefirstchar",
+ arguments = "2 strings",
+ actions = function(str,chr)
+ ctx_doifelse(lpegmatch(pattern,str) == chr)
+ end
+}
+
+implement {
+ name = "getsubstring",
+ arguments = "3 strings",
+ actions = function(str,first,last)
+ context(utfsub(str,tonumber(first),tonumber(last)))
+ end
+}
+
+-- function commands.addtocommalist(list,item)
+-- if list == "" then
+-- context(item)
+-- else
+-- context("%s,%s",list,item) -- using tex.print is some 10% faster
+-- end
+-- end
+--
+-- function commands.removefromcommalist(list,item)
+-- if list == "" then
+-- context(item)
+-- else
+-- -- okay, using a proper lpeg is probably faster
+-- -- we could also check for #l = 1
+-- local l = settings_to_array(list)
+-- local t, n = { }
+-- for i=1,#l do
+-- if l[i] ~= item then
+-- n = n + 1
+-- t[n] = item
+-- end
+-- end
+-- if n == 0 then
+-- context(item)
+-- else
+-- context(concat(list,","))
+-- end
+-- end
+-- end
+
+local pattern = (C((1-P("%"))^1) * Carg(1)) / function(n,d)
+ return formatters["%.0fsp"](d * tonumber(n)/100) end * P("%") * P(-1) -- .0 ?
+
+-- percentageof("10%",65536*10)
+
+implement {
+ name = "percentageof",
+ arguments = { "string", "dimen" },
+ actions = function(str,dim)
+ context(lpegmatch(pattern,str,1,dim) or str)
+ end
+}
+
+-- \gdef\setpercentdimen#1#2%
+-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
+
+local space = P(" ") / ""
+local spaces = P(" ")^0 / ""
+local nohash = 1 - P("#")
+local digit = R("09")
+local double = P("##") / "#"
+local single = P("#")
+local sentinel = spaces * (nohash^1 / "\\%0")
+local whatever = S("+-/*_^=:") + digit
+local sargument = (single * digit)^1
+local dargument = (double * digit)^1
+local swhatever = (single * whatever)^1
+local dwhatever = (double * whatever)^1
+
+-- different ones:
+
+local space = P(" ")
+local spaces = space^0
+
+-- see syst-aux.lua for historic variants
+
+local global = nil
+local protected = nil
+local expanded = nil
+local optional = nil
+local tolerant = nil
+local instance = nil
+local frozen = nil
+local csname = nil
+local rest = nil
+
+local function catcodes_s()
+ setcatcode(32,10) -- space
+ setcatcode(13, 5) -- endofline
+end
+
+local function catcodes_n()
+ setcatcode(32, 9) -- ignore
+ setcatcode(13, 9) -- ignore
+end
+
+local function oldoption(s)
+ if optional > 1 then
+ optional = optional - 1
+ return s .. "#*"
+ else
+ return s
+ end
+end
+
+local option = (
+ P("single") * Cc(1)
+ + P("double") * Cc(2)
+ + P("triple") * Cc(3)
+ + P("quadruple") * Cc(4)
+ + P("quintuple") * Cc(5)
+ + P("sixtuple")
+ ) * (P("empty") + P("argument"))
+
+local pattern = (
+ (
+ spaces * (
+ ( P("spaces") * space / catcodes_s )
+ + ( P("nospaces") * space / catcodes_n )
+ + ( P("global") * space / function() global = true end)
+ + ( P("protected") * space / function() protected = true end)
+ + ( P("expanded") * space / function() expanded = true end)
+ + ( P("tolerant") * space / function() tolerant = true end)
+ + ( P("instance") * space / function() instance = true end)
+ + ( P("frozen") * space / function() frozen = true end)
+ + ( P("unexpanded") * space / function() protected = true end)
+ + ( option * space / function(s) tolerant = true
+ optional = s end)
+ )
+ )^0
+ * spaces * ( C((1-S(" #["))^1) )
+ * spaces * Cs(
+ (Cs(P("[") * dargument * P("]")) / oldoption + dwhatever)^1 * sentinel^-1 * double^-1
+ + (Cs(P("[") * sargument * P("]")) / oldoption + swhatever)^1 * sentinel^-1 * single^-1
+ + sentinel^-1 * (double+single)^-1
+ )
+)
+
+local ctx_dostarttexdefinition = context.dostarttexdefinition
+
+local function texdefinition_one(str)
+ global = false
+ protected = false
+ expanded = false
+ optional = 0
+ tolerant = false
+ instance = false
+ frozen = false
+ csname, rest = lpegmatch(pattern,str)
+ ctx_dostarttexdefinition()
+end
+
+local function texdefinition_two()
+ context (
+ (tolerant and [[\tolerant]] or "") .. (frozen and [[\frozen]] or "") .. (protected and [[\protected]] or "") .. (instance and [[\instance]] or "") ..
+ [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) ..
+ [[\csname ]] .. csname .. [[\endcsname ]] ..
+ rest
+ )
+end
+
+implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" }
+implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" }
+
+do
+
+ -- Quite probably we don't yet have characters loaded so we delay some
+ -- aliases.
+
+ local _lower_, _upper_, _strip_
+
+ _lower_ = function(s)
+ if characters and characters.lower then
+ _lower_ = characters.lower
+ return _lower_(s)
+ end
+ return string.lower(s)
+ end
+
+ _upper_ = function(s)
+ if characters and characters.upper then
+ _upper_ = characters.upper
+ return _upper_(s)
+ end
+ return string.upper(s)
+ end
+
+ _strip_ = function(s)
+ -- or utf.strip
+ if string.strip then
+ _strip_ = string.strip
+ return _strip_(s)
+ end
+ return s
+ end
+
+ local function lower(s) context(_lower_(s)) end
+ local function upper(s) context(_upper_(s)) end
+ local function strip(s) context(_strip_(s)) end
+
+ implement { name = "upper", arguments = "string", actions = upper }
+ implement { name = "lower", arguments = "string", actions = lower }
+ implement { name = "strip", arguments = "string", actions = strip }
+
+end
+
+implement {
+ name = "converteddimen",
+ arguments = { "dimen", "string" },
+ actions = function(dimen,unit)
+ context(number.todimen(dimen,unit or "pt","%0.5f")) -- no unit appended (%F)
+ end
+}
+
+-- where, not really the best spot for this:
+
+implement {
+ name = "immediatemessage",
+ arguments = { "'message'", "string" },
+ actions = logs.status
+}
+
+implement {
+ name = "resettimer",
+ actions = function()
+ statistics.resettiming("whatever")
+ statistics.starttiming("whatever")
+ end
+}
+
+implement {
+ name = "benchmarktimer",
+ actions = function()
+ statistics.benchmarktimer("whatever")
+ end
+}
+
+implement {
+ name = "elapsedtime",
+ actions = function()
+ statistics.stoptiming("whatever")
+ context(statistics.elapsedtime("whatever"))
+ end
+}
+
+implement {
+ name = "elapsedsteptime",
+ arguments = "integer",
+ actions = function(n)
+ statistics.stoptiming("whatever")
+ local t = statistics.elapsed("whatever")/(n > 0 and n or 1)
+ if t > 0 then
+ context("%0.9f",t)
+ else
+ context(0)
+ end
+ end
+}
+
+local accuracy = table.setmetatableindex(function(t,k)
+ local v = formatters["%0." ..k .. "f"]
+ t[k] = v
+ return v
+end)
+
+implement {
+ name = "rounded",
+ arguments = "integer",
+ actions = function(n,m) context(accuracy[n](m)) end
+}
+
+-- not faster but just less tracing:
+
+local ctx_protected_cs = context.protected.cs -- more efficient
+
+local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments
+local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments
+local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument
+local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument
+
+context.firstoftwoarguments = ctx_firstoftwoarguments
+context.secondoftwoarguments = ctx_secondoftwoarguments
+context.firstofoneargument = ctx_firstofoneargument
+context.gobbleoneargument = ctx_gobbleoneargument
+
+local ctx_iftrue = context.iftrue
+local ctx_iffalse = context.iffalse
+
+local hash = utilities.parsers.hashes.settings_to_set
+
+local function doifelsecommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_secondoftwoarguments()
+ else
+ ctx_firstoftwoarguments()
+ end
+ return
+ end
+ local ba = find(a,",",1,true)
+ local bb = find(b,",",1,true)
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ ctx_firstoftwoarguments()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ ctx_firstoftwoarguments()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_firstoftwoarguments()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_secondoftwoarguments()
+end
+
+local function doifcommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_gobbleoneargument()
+ else
+ ctx_firstofoneargument()
+ end
+ return
+ end
+ local ba = find(a,",",1,true)
+ local bb = find(b,",",1,true)
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ ctx_firstofoneargument()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ ctx_firstofoneargument()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_firstofoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_gobbleoneargument()
+end
+
+local function doifnotcommon(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_firstofoneargument()
+ else
+ ctx_gobbleoneargument()
+ end
+ return
+ end
+ local ba = find(a,",",1,true)
+ local bb = find(b,",",1,true)
+ if ba and bb then
+ local ha = hash[a]
+ local hb = hash[b]
+ -- local ha = settings_to_set(a)
+ -- local hb = settings_to_set(b)
+ for k in next, ha do
+ if hb[k] then
+ setmacro("commalistelement",k)
+ ctx_gobbleoneargument()
+ return
+ end
+ end
+ elseif ba then
+ if hash[a][b] then
+ -- if settings_to_set(a)[b] then
+ setmacro("commalistelement",b)
+ ctx_gobbleoneargument()
+ return
+ end
+ elseif bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_gobbleoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_firstofoneargument()
+end
+
+-- local function hascommonargumentcondition(a,b)
+-- if a == b then
+-- setmacro("commalistelement",a)
+-- if a == "" then
+-- ctx_iffalse()
+-- else
+-- ctx_iftrue()
+-- end
+-- return
+-- end
+-- local ba = find(a,",",1,true)
+-- local bb = find(b,",",1,true)
+-- if ba and bb then
+-- local ha = hash[a]
+-- local hb = hash[b]
+-- for k in next, ha do
+-- if hb[k] then
+-- setmacro("commalistelement",k)
+-- ctx_iftrue()
+-- return
+-- end
+-- end
+-- elseif ba then
+-- if hash[a][b] then
+-- setmacro("commalistelement",b)
+-- ctx_iftrue()
+-- return
+-- end
+-- elseif bb then
+-- if hash[b][a] then
+-- setmacro("commalistelement",a)
+-- ctx_iftrue()
+-- return
+-- end
+-- end
+-- setmacro("commalistelement","")
+-- ctx_iffalse()
+-- end
+
+local function doifelseinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_secondoftwoarguments()
+ else
+ ctx_firstoftwoarguments()
+ end
+ return
+ end
+ local bb = find(b,",",1,true)
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_firstoftwoarguments()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_secondoftwoarguments()
+end
+
+local function doifinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_gobbleoneargument()
+ else
+ ctx_firstofoneargument()
+ end
+ return
+ end
+ local bb = find(b,",",1,true)
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_firstofoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_gobbleoneargument()
+end
+
+local function doifnotinset(a,b)
+ if a == b then
+ setmacro("commalistelement",a)
+ if a == "" then
+ ctx_firstofoneargument()
+ else
+ ctx_gobbleoneargument()
+ end
+ return
+ end
+ local bb = find(b,",",1,true)
+ if bb then
+ if hash[b][a] then
+ -- if settings_to_set(b)[a] then
+ setmacro("commalistelement",a)
+ ctx_gobbleoneargument()
+ return
+ end
+ end
+ setmacro("commalistelement","")
+ ctx_firstofoneargument()
+end
+
+implement {
+ name = "doifelsecommon",
+ actions = doifelsecommon,
+ arguments = "2 strings",
+}
+
+implement {
+ name = "doifcommon",
+ actions = doifcommon,
+ arguments = "2 strings",
+}
+
+implement {
+ name = "doifnotcommon",
+ actions = doifnotcommon,
+ arguments = "2 strings",
+}
+
+-- implement {
+-- name = "hascommonargumentcondition",
+-- actions = hascommonargumentcondition,
+-- arguments = "2 strings",
+-- arguments = { "argument", "argument" },
+-- }
+
+implement {
+ name = "doifelseinset",
+ actions = doifelseinset,
+ arguments = "2 strings",
+-- arguments = { "argument", "argument" },
+}
+
+implement {
+ name = "doifinset",
+ actions = doifinset,
+ arguments = "2 strings",
+}
+
+implement {
+ name = "doifnotinset",
+ actions = doifnotinset,
+ arguments = "2 strings",
+}
+
+-- done elsewhere:
+--
+-- local function firstinset(a)
+-- local aa = hash[a]
+-- context(aa and aa[1] or a)
+-- end
+--
+-- implement {
+-- name = "firstinset",
+-- actions = firstinset,
+-- arguments = "string",
+-- private = false,
+-- }
+
+-- implement {
+-- name = "stringcompare",
+-- arguments = "2 strings",
+-- actions = function(a,b)
+-- context((a == b and 0) or (a > b and 1) or -1)
+-- end
+-- }
+--
+-- implement {
+-- name = "doifelsestringafter",
+-- arguments = "2 strings",
+-- actions = function(a,b)
+-- ctx_doifelse((a == b and 0) or (a > b and 1) or -1)
+-- end
+-- }
+--
+-- implement {
+-- name = "doifelsestringbefore",
+-- arguments = "2 strings",
+-- actions = function(a,b)
+-- ctx_doifelse((a == b and 0) or (a < b and -1) or 1)
+-- end
+-- }
+
+-- implement { -- not faster than addtocommalist
+-- name = "additemtolist", -- unique
+-- arguments = "2 strings",
+-- actions = function(l,s)
+-- if l == "" or s == l then
+-- -- s = s
+-- elseif find("," .. l .. ",","," .. s .. ",") then
+-- s = l
+-- else
+-- s = l .. "," .. s
+-- end
+-- context(s)
+-- end
+-- }
+
+local bp = number.dimenfactors.bp
+
+implement {
+ name = "tobigpoints",
+ actions = function(d) context("%.5F",bp * d) end,
+ arguments = "dimension",
+}
+
+implement {
+ name = "towholebigpoints",
+ actions = function(d) context("%r",bp * d) end,
+ arguments = "dimension",
+}
+
+-- for now here:
+
+local function getshape(s)
+ local t = texget(s)
+ local n = t and #t or 0
+ context(n)
+ if n > 0 then
+ for i=1,n do
+ local ti = t[i]
+ if type(ti) == "table" then
+ context(" %isp %isp",ti[1],ti[2])
+ else
+ context(" %i",ti)
+ end
+ end
+ end
+end
+
+implement {
+ name = "getparshape",
+ public = true,
+ actions = function() getshape("parshape") end,
+}
+implement {
+ name = "getclubpenalties",
+ public = true,
+ actions = function() getshape("clubpenalties") end,
+}
+implement {
+ name = "getinterlinepenalties",
+ public = true,
+ actions = function() getshape("interlinepenalties") end,
+ }
+implement {
+ name = "getdisplaywidowpenalties",
+ public = true,
+ actions = function() getshape("displaywidowpenalties") end,
+}
+implement {
+ name = "getwidowpenalties",
+ public = true,
+ actions = function() getshape("widowpenalties") end,
+}
diff --git a/tex/context/base/mkiv/syst-aux.lua b/tex/context/base/mkiv/syst-aux.lua
index 05a070d30..859e40ead 100644
--- a/tex/context/base/mkiv/syst-aux.lua
+++ b/tex/context/base/mkiv/syst-aux.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['syst-aux'] = {
+ if not modules then modules = { } end modules ['syst-aux'] = {
version = 1.001,
comment = "companion to syst-aux.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -233,12 +233,12 @@ local dargument = (double * digit)^1
-- third variant:
-local global = nil
-local unexpanded = nil
-local expanded = nil
-local optional = nil
-local csname = nil
-local rest = nil
+local global = nil
+local unexpanded = nil
+local expanded = nil
+local optional = nil
+local csname = nil
+local rest = nil
local function catcodes_s()
setcatcode(32,10) -- space
@@ -262,13 +262,40 @@ local option = (
+ P("sixtuple")
) * (P("empty") + P("argument"))
+-- local pattern = (
+-- ( P("spaces") * space / catcodes_s )^0
+-- * spaces * ( P("nospaces") * space / catcodes_n )^0
+-- * spaces * ( P("global") * space * Cc(true) + Cc(false) )
+-- * spaces * ( P("unexpanded") * space * Cc(true) + Cc(false) )
+-- * spaces * ( P("expanded") * space * Cc(true) + Cc(false) )
+-- * spaces * ( C(option) * space + Cc(false) )
+-- * spaces * ( C((1-S(" #["))^1) )
+-- * spaces * Cs(
+-- ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1
+-- + ( P("[") * sargument * P("]") + sargument)^1 * sentinel^-1 * single^-1
+-- + sentinel^-1 * (double+single)^-1
+-- )
+-- )
+--
+-- local ctx_dostarttexdefinition = context.dostarttexdefinition
+--
+-- local function texdefinition_one(str)
+-- global, unexpanded, expanded, optional, csname, rest = lpegmatch(pattern,str)
+-- ctx_dostarttexdefinition()
+-- end
+
local pattern = (
- ( P("spaces") * space / catcodes_s )^0
- * spaces * ( P("nospaces") * space / catcodes_n )^0
- * spaces * ( P("global") * space * Cc(true) + Cc(false) )
- * spaces * ( P("unexpanded") * space * Cc(true) + Cc(false) )
- * spaces * ( P("expanded") * space * Cc(true) + Cc(false) )
- * spaces * ( C(option) * space + Cc(false) )
+ (
+ spaces * (
+ ( P("spaces") * space / catcodes_s )
+ + ( P("nospaces") * space / catcodes_n )
+ + ( P("global") * space / function() global = true end )
+ + ( P("unexpanded") * space / function() unexpanded = true end )
+ + ( P("protected") * space / function() unexpanded = true end )
+ + ( P("expanded") * space / function() expanded = true end )
+ + ( C(option) * space / function(s) optional = s end )
+ )
+ )^0
* spaces * ( C((1-S(" #["))^1) )
* spaces * Cs(
( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1
@@ -280,40 +307,29 @@ local pattern = (
local ctx_dostarttexdefinition = context.dostarttexdefinition
local function texdefinition_one(str)
- global, unexpanded, expanded, optional, csname, rest = lpegmatch(pattern,str)
+ global = false
+ unexpanded = false
+ expanded = false
+ optional = false
+ csname, rest = lpegmatch(pattern,str)
ctx_dostarttexdefinition()
end
local function texdefinition_two()
if optional then
context (
- [[\unexpanded\expandafter]] ..
- (global and [[\xdef]] or [[\edef]]) ..
- [[\csname ]] ..
- csname ..
- [[\endcsname{\expandafter\noexpand\expandafter\do]] ..
- optional ..
- [[\csname _do_]] ..
- csname ..
- -- [[_\endcsname}\unexpanded\expandafter]] ..
- [[_\endcsname}\expandafter]] ..
- (global and [[\gdef]] or [[\edef]]) ..
- [[\csname _do_]] ..
- csname ..
- [[_\endcsname ]] ..
+ (unexpanded and [[\unexpanded]] or "") ..
+ [[\expandafter]] .. (global and [[\xdef]] or [[\edef]]) ..
+ [[\csname ]] .. csname .. [[\endcsname{\expandafter\noexpand\expandafter\do]] .. optional ..
+ [[\csname _do_]] .. csname .. [[_\endcsname}\expandafter]] .. (global and [[\gdef]] or [[\edef]]) ..
+ [[\csname _do_]] .. csname .. [[_\endcsname ]] ..
rest
)
else
context (
- [[\unexpanded\expandafter]] ..
- ( global and (
- expanded and [[\xdef]] or [[\gdef]]
- ) or (
- expanded and [[\edef]] or [[\def]]
- ) ) ..
- [[\csname ]] ..
- csname ..
- [[\endcsname ]] ..
+ (unexpanded and [[\unexpanded]] or "") ..
+ [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) ..
+ [[\csname ]] .. csname .. [[\endcsname ]] ..
rest
)
end
diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv
index 2d1ae17be..29f05c9b8 100644
--- a/tex/context/base/mkiv/syst-aux.mkiv
+++ b/tex/context/base/mkiv/syst-aux.mkiv
@@ -56,21 +56,10 @@
\let\unexpanded\normalprotected
-\ifcase\contextlmtxmode
-
- \def\startlmtxmode#1\stoplmtxmode{}
- \let\stoplmtxmode \relax
- \let\startmkivmode\relax
- \let\stopmkivmode \relax
-
-\else
-
- \let\startlmtxmode\relax
- \let\stoplmtxmode \relax
- \def\startmkivmode#1\stopmkivmode{}
- \let\stopmkivmode \relax
-
-\fi
+\def\startlmtxmode#1\stoplmtxmode{}
+\let\stoplmtxmode \relax
+\let\startmkivmode\relax
+\let\stopmkivmode \relax
%D As we don't have namespace definers yet, we use a special one:
diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl
index 95a1079e8..4f3b65ad8 100644
--- a/tex/context/base/mkiv/syst-aux.mkxl
+++ b/tex/context/base/mkiv/syst-aux.mkxl
@@ -11,7 +11,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\registerctxluafile{syst-aux}{}
+%D In the process of being adapted to \LMTX\ flags so a bit of a mess now. Also
+%D our playground.
+
+\registerctxluafile{syst-aux}{autosuffix}
\registerctxluafile{syst-mac}{autosuffix}
%D This file is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv} where
@@ -46,14 +49,18 @@
%D keep the same name for a similar mechanism. So, effectively we have two ways to
%D protect a macro.
-\let\unexpanded\normalprotected
+\pushoverloadmode
+
+\aliased\let\unexpanded\normalprotected
+
+\popoverloadmode
%D We're definitely in \LMTX\ mode here.
-\let\startlmtxmode\relax
-\let\stoplmtxmode \relax
-\def\startmkivmode#-\stopmkivmode{}
-\let\stopmkivmode \relax
+\aliased \let\startlmtxmode\relax
+\aliased \let\stoplmtxmode \relax
+\permanent\def\startmkivmode#-\stopmkivmode{}
+\aliased \let\stopmkivmode \relax
%D As we don't have namespace definers yet, we use a special one. Later we will
%D do a better job.
@@ -71,7 +78,7 @@
\fi
-\protected\def\installsystemnamespace#1% maybe move this to syst-ini
+\permanent\protected\def\installsystemnamespace#1% maybe move this to syst-ini
{\ifcsname ??#1\endcsname
\writestatus\m!system{duplicate system namespace '#1'}\wait
\else
@@ -144,24 +151,25 @@
%D that's the price to pay. More are defined elsewhere. Of course we later pay a
%D price when they need to be expanded.
-\def\v!prefix! {v!}
-\def\c!prefix! {c!}
-\def\s!prefix! {s!}
-
-\def\s!next {next}
-\def\s!default {default}
-\def\s!dummy {dummy}
-\def\s!unknown {unknown}
-
-\def\s!do {do}
-\def\s!dodo {dodo}
-
-\def\s!complex {complex}
-\def\s!start {start}
-\def\s!simple {simple}
-\def\s!stop {stop}
+% \def\v!prefix! {v!}
+% \def\c!prefix! {c!}
+% \def\s!prefix! {s!}
+%
+% \def\s!next {next}
+% \def\s!default {default}
+% \def\s!dummy {dummy}
+% \def\s!unknown {unknown}
+%
+% \def\s!do {do}
+% \def\s!dodo {dodo}
+%
+% \def\s!complex {complex}
+% \def\s!simple {simple}
+%
+% \def\s!start{start}
+% \def\s!stop {stop}
-\def\s!empty {empty}
+% \immutable\def\s!empty {empty}
%D Sometimes we pass macros as arguments to commands that don't expand them before
%D interpretation. Such commands can be enclosed with \type {\expanded}, like:
@@ -178,13 +186,17 @@
\let\m_syst_helpers_expanded\empty
-\protected\def\expanded#1%
+\pushoverloadmode
+
+\permanent\protected\def\expanded#1%
{\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded}
-\protected\def\startexpanded#1\stopexpanded
+\popoverloadmode
+
+\permanent\protected\def\startexpanded#1\stopexpanded
{\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded}
-\let\stopexpanded\relax
+\aliased\let\stopexpanded\relax
%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when
%D possible. After all, we can make not expandable macros now. The name clash is an
@@ -207,21 +219,21 @@
%D is more efficient but it probably won't be noticed. It's anyway cheaper on memory
%D access. We use versions that don't even store the arguments.
-\def\gobbleoneargument #-{}
-\def\gobbletwoarguments #-#-{}
-\def\gobblethreearguments #-#-#-{}
-\def\gobblefourarguments #-#-#-#-{}
-\def\gobblefivearguments #-#-#-#-{}
-\def\gobblesixarguments #-#-#-#-{}
-\def\gobblesevenarguments #-#-#-#-#-{}
-\def\gobbleeightarguments #-#-#-#-#-#-{}
-\def\gobbleninearguments #-#-#-#-#-#-#-{}
-
-\def\gobbleoneoptional [#-]{}
-\def\gobbletwooptionals [#-][#-]{}
-\def\gobblethreeoptionals[#-][#-][#-]{}
-\def\gobblefouroptionals [#-][#-][#-][#-]{}
-\def\gobblefiveoptionals [#-][#-][#-][#-][#-]{}
+%def\gobbleoneargument #-{}
+\permanent\def\gobbletwoarguments #-#-{}
+\permanent\def\gobblethreearguments #-#-#-{}
+\permanent\def\gobblefourarguments #-#-#-#-{}
+\permanent\def\gobblefivearguments #-#-#-#-{}
+\permanent\def\gobblesixarguments #-#-#-#-{}
+\permanent\def\gobblesevenarguments #-#-#-#-#-{}
+\permanent\def\gobbleeightarguments #-#-#-#-#-#-{}
+\permanent\def\gobbleninearguments #-#-#-#-#-#-#-{}
+
+\permanent\def\gobbleoneoptional [#-]{}
+\permanent\def\gobbletwooptionals [#-][#-]{}
+\permanent\def\gobblethreeoptionals[#-][#-][#-]{}
+\permanent\def\gobblefouroptionals [#-][#-][#-][#-]{}
+\permanent\def\gobblefiveoptionals [#-][#-][#-][#-][#-]{}
%D Reserved macros for tests:
@@ -242,10 +254,10 @@
%D blank spaces but in the meantime we can use some \LUATEX\ trickery. Older versions
%D use more code and can be find in the \MKIV\ and \MKII\ files.
-\let\next \relax
-\let\nextnext \relax % kind of obsolete
-\let\nextnextnext \relax % kind of obsolete
-\let\nexttoken \relax
+% \mutable\let\next \relax
+% \mutable\let\nextnext \relax % kind of obsolete
+% \mutable\let\nextnextnext \relax % kind of obsolete
+% \mutable\let\nexttoken \relax
\let\m_syst_action_yes\relax
\let\m_syst_action_nop\relax
@@ -383,21 +395,37 @@
%D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to
%D its object oriented and parameter driven character.
-\def\setvalue #1{\expandafter\def \csname#1\endcsname}
-\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
-\def\setevalue #1{\expandafter\edef\csname#1\endcsname}
-\def\setxvalue #1{\expandafter\xdef\csname#1\endcsname}
+% \def\setvalue #1{\expandafter\def \csname#1\endcsname}
+% \def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
+% \def\setevalue #1{\expandafter\edef\csname#1\endcsname}
+% \def\setxvalue #1{\expandafter\xdef\csname#1\endcsname}
+% \def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname
+% \def\letvalue #1{\expandafter\let \csname#1\endcsname}
+% \def\letgvalue #1{\expandafter\glet\csname#1\endcsname}
+% \def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty}
+% \def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined}
+% \def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty}
+
+\def\setvalue #1{\expandafter\defcsname#1\endcsname}
+\def\setgvalue #1{\global\defcsname#1\endcsname}
+\def\setevalue #1{\edefcsname#1\endcsname}
+\def\setxvalue #1{\global\edefcsname#1\endcsname}
\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname
-\def\letvalue #1{\expandafter\let \csname#1\endcsname}
-\def\letgvalue #1{\expandafter\glet\csname#1\endcsname}
-\def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty}
-\def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined}
-\def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty}
-
-\def\setuvalue #1{\protected\expandafter \def\csname#1\endcsname}
-\def\setuevalue #1{\protected\expandafter\edef\csname#1\endcsname}
-\def\setugvalue #1{\protected\expandafter\gdef\csname#1\endcsname}
-\def\setuxvalue #1{\protected\expandafter\xdef\csname#1\endcsname}
+\def\letvalue #1{\letcsname#1\endcsname}
+\def\letgvalue #1{\global\letcsname#1\endcsname}
+\def\resetvalue #1{\letcsname#1\endcsname\empty}
+\def\undefinevalue#1{\letcsname#1\endcsname\undefined}
+\def\ignorevalue#1#2{\letcsname#1\endcsname\empty}
+
+% \def\setuvalue #1{\protected\expandafter \def\csname#1\endcsname}
+% \def\setuevalue #1{\protected\expandafter\edef\csname#1\endcsname}
+% \def\setugvalue #1{\protected\expandafter\gdef\csname#1\endcsname}
+% \def\setuxvalue #1{\protected\expandafter\xdef\csname#1\endcsname}
+
+\def\setuvalue #1{\protected\defcsname#1\endcsname}
+\def\setuevalue #1{\protected\edefcsname#1\endcsname}
+\def\setugvalue #1{\protected\global\defcsname#1\endcsname}
+\def\setuxvalue #1{\protected\global\edefcsname#1\endcsname}
\protected\def\getuvalue#1{\csname#1\endcsname}
@@ -798,24 +826,40 @@
%D arguments state. Again it permits leaner and meaner macro definitions with a bit
%D less clutter in tracing.
-\protected\def\syst_helpers_process_comma_item#1,%
+\let\commalistcommand\empty
+
+\protected\def\syst_helpers_process_comma_item#+,%
{\ifarguments
\expandafter\syst_helpers_process_comma_item_gobble
- \or
+ \orelse\ifparameter#1\or
\commalistcommand{#1}%
\expandafter\syst_helpers_process_comma_item_next
+ \else
+ \expandafter\syst_helpers_process_comma_item_gobble
\fi}
\def\syst_helpers_process_comma_item_next
{\expandafterspaces\syst_helpers_process_comma_item}
-\protected\def\processcommalist[#1]#2%
+% \protected\def\processcommalist[#1]#2%
+% {\pushmacro\commalistcommand
+% \def\commalistcommand{#2}%
+% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments
+% \popmacro\commalistcommand}
+
+% \protected\def\processcommacommand[#1]#2%
+% {\pushmacro\commalistcommand
+% \def\commalistcommand{#2}%
+% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments
+% \popmacro\commalistcommand}
+
+\protected\def\processcommalist[#*#+]#2%
{\pushmacro\commalistcommand
\def\commalistcommand{#2}%
\expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments
\popmacro\commalistcommand}
-\protected\def\processcommacommand[#1]#2%
+\protected\def\processcommacommand[#*#+]#2%
{\pushmacro\commalistcommand
\def\commalistcommand{#2}%
\normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments
@@ -964,7 +1008,7 @@
\let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b
\fi
\edef\syst_helpers_do_process_action##1{\syst_helpers_do_compare_process_action[##1][#1]}% expands #1
- \processnextcommalist\relax\relax\syst_helpers_do_process_action[}
+ \processnextcommalist\syst_helpers_do_process_action[}
\protected\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]%
{\edef\m_syst_string_one{#1}%
@@ -990,10 +1034,10 @@
\fi
[#1]}
-\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#2[#3]%
+\tolerant\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#*[#2]%
{\def\syst_helpers_do_process_action##1%
{\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}%
- \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \processcommalist[#2]\syst_helpers_do_do_process_action}%
\normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action}
\protected\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]%
@@ -1011,12 +1055,12 @@
\fi
\fi}
-\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]%
+\tolerant\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#*[#2]%
{\globalpushmacro\syst_process_action_in_set_all
\def\syst_process_action_in_set##1%
{\def\syst_process_action_in_set_one####1{\syst_helpers_do_compare_process_action_d[####1][##1]}%
- \processcommalist[#3]\syst_process_action_in_set_one}%
- \processcommacommand[#1]\syst_process_action_in_set
+ \processcommalist[#2]\syst_process_action_in_set_one}%
+ \processcommacommand[#1]\syst_process_action_in_set
\globalpopmacro\syst_process_action_in_set_all}
\protected\def\processallactionsinset[#1]%
@@ -1025,18 +1069,21 @@
\expandafter\processaction
\else
\expandafter\syst_helpers_process_all_actions_in_set_indeed
- \fi
- [#1]}
+ \fi[#1]}
%D These macros use:
-\protected\def\processnextcommalist#1#2#3[#4#5]%
- {#1\relax
- \pushmacro\commalistcommand
- \def\commalistcommand{#3}%
- \expandafterspaces\syst_helpers_process_comma_item#4#5\ignorearguments\ignorearguments\ignorearguments
- \popmacro\commalistcommand
- #2\relax}
+% \protected\def\processnextcommalist#1[#2#3]%
+% {\pushmacro\commalistcommand
+% \def\commalistcommand{#1}%
+% \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments
+% \popmacro\commalistcommand}
+
+\protected\def\processnextcommalist#1[#2#3]%
+ {\pushmacro\commalistcommand
+ \def\commalistcommand{#1}%
+ \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments
+ \popmacro\commalistcommand}
%D \macros
%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter}
@@ -1281,10 +1328,12 @@
\processcommalist[#1]\syst_helpers_do_make_raw_comma_list
\edef#2{\the\scratchtoks}}
-\let\rawprocesscommalist \processcommalist
-\let\rawprocesscommacommand\processcommacommand
+% beware: in mkiv { } were lost so it was not compatible with the non raw
-%D Here is one without nesting:
+\let\rawprocesscommalist \processcommalist % can go
+\let\rawprocesscommacommand\processcommacommand % can go
+
+%D Here is one without nesting .. still needed?
\protected\def\syst_helpers_process_fast_comma_item#1,%
{\ifarguments
@@ -1410,20 +1459,6 @@
\def\doignorevalue#1#2#3{\expandafter\let \csname#1#2\endcsname\empty}
\def\docopyvalue #1#2#3{\expandafter\def \csname#1#3\endcsname{\csname#2#3\endcsname}}
-%D Experiment
-%D
-%D \starttyping
-%D \protected\def\fooA{A} \aliasmacro\FooA\fooA
-%D \def\fooB{B} \aliasmacro\FooB\fooB
-%D
-%D \meaning\fooA\crlf \meaning\FooA\crlf
-%D \meaning\fooB\crlf \meaning\FooB\crlf
-%D \stoptyping
-
-\protected\def\aliasmacro#1#2%
- {\ifprotected#2\protected\protected\fi
- \def#1{#2}}
-
%D \macros
%D {doassign,undoassign,doassignempty}
%D
@@ -1559,12 +1594,11 @@
\def\syst_helpers_grab_parameter_next
{\expandafterspaces\syst_helpers_grab_parameter}
-\protected\def\dogetparameters#1[#2]#-[#3]%
+\protected\def\dogetparameters#1[#2]#*[#3]%
{\def\m_syst_parameter_n{#2}%
\let\m_syst_parameter_s#1%
\expandafterspaces\syst_helpers_grab_parameter#3\ignorearguments\ignorearguments}
-
%D \macros
%D {getemptyparameters}
%D
@@ -1575,9 +1609,9 @@
%D \getemptyparameters [label] [...=...,...=...]
%D \stoptyping
-\protected\def\getemptyparameters[#1]#2[#3]%
+\protected\def\getemptyparameters[#1]#*[#2]%
{\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}%
- \processcommalist[#3]\syst_helpers_get_empty_parameters}
+ \processcommalist[#2]\syst_helpers_get_empty_parameters}
%D We now just alias these as there is no need for a speedup. These have not been used
%D for a long time in core code.
@@ -1658,7 +1692,7 @@
%D By using \type {\docopyvalue} we've prepared this command for use in a
%D multi||lingual environment.
-\protected\def\copyparameters[#1]#-[#2]#-[#3]%
+\protected\def\copyparameters[#1]#*[#2]#*[#3]%
{\doifnot{#1}{#2}
{\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#2}}% ##1
\processcommalist[#3]\syst_helpers_copy_parameter}}
@@ -1753,9 +1787,9 @@
\def\syst_helpers_get_from_comma_list_next
{\expandafterspaces\syst_helpers_get_from_comma_list}
-\protected\def\getfromcommalist[#1]#2[#3]%
+\protected\def\getfromcommalist[#1]#*[#2]%
{\let\commalistelement\empty
- \commalistcounter#3\relax
+ \commalistcounter#2\relax
\expandafterspaces\syst_helpers_get_from_comma_list#1\ignorearguments\ignorearguments}
\protected\def\getfromcommacommand[#1]%
@@ -1860,6 +1894,8 @@
%D We use some signals for telling the calling macros if all wanted arguments are
%D indeed supplied by the user.
+\newcount\nofarguments
+
\newif\iffirstargument
\newif\ifsecondargument
\newif\ifthirdargument
@@ -1902,328 +1938,420 @@
\newtoks\t_syst_aux
-\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux}
-\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux}
-\def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux}
-\def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux}
-\def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux}
-\def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux}
-\def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux}
-
-%D Single:
-
-\protected\def\dosingleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop}
-
-\def\syst_helpers_single_empty_one_nop
- {\firstargumentfalse
- \the\t_syst_aux[]}
-
-%D Double
-
-\protected\def\dodoubleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop}
-
-\def\syst_helpers_double_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop}
-
-\def\syst_helpers_double_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_double_empty_two_nop
- {\secondargumentfalse
- \the\t_syst_aux[]}
-
-% Triple
-
-\protected\def\dotripleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop}
-
-\def\syst_helpers_triple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop}
-
-\def\syst_helpers_triple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop}
-
-\def\syst_helpers_triple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux[][][]}
-
-\def\syst_helpers_triple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_triple_empty_three_nop
- {\thirdargumentfalse
- \the\t_syst_aux[]}
-
-%D Quadruple:
-
-\protected\def\doquadrupleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop}
-
-\def\syst_helpers_quadruple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop}
-
-\def\syst_helpers_quadruple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop}
-
-\def\syst_helpers_quadruple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop}
-
-\def\syst_helpers_quadruple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][][][]}
-
-\def\syst_helpers_quadruple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][][]}
-
-\def\syst_helpers_quadruple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_quadruple_empty_four_nop
- {\fourthargumentfalse
- \the\t_syst_aux[]}
-
-%D Quintuple:
-
-\protected\def\doquintupleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop}
-
-\def\syst_helpers_quintuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop}
-
-\def\syst_helpers_quintuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop}
-
-\def\syst_helpers_quintuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop}
-
-\def\syst_helpers_quintuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop}
-
-\def\syst_helpers_quintuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][][][]}
-
-\def\syst_helpers_quintuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][][]}
-
-\def\syst_helpers_quintuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][][]}
-
-\def\syst_helpers_quintuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_quintuple_empty_five_nop
- {\fifthargumentfalse
- \the\t_syst_aux[]}
-
-%D Sixtuple:
-
-\protected\def\dosixtupleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop}
-
-\def\syst_helpers_sixtuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop}
-
-\def\syst_helpers_sixtuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop}
-
-\def\syst_helpers_sixtuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop}
-
-\def\syst_helpers_sixtuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop}
-
-\def\syst_helpers_sixtuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop}
-
-\def\syst_helpers_sixtuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][][][]}
-
-\def\syst_helpers_sixtuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][][]}
-
-\def\syst_helpers_sixtuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][][]}
-
-\def\syst_helpers_sixtuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][][]}
-
-\def\syst_helpers_sixtuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_sixtuple_empty_six_nop
- {\sixthargumentfalse
- \the\t_syst_aux[]}
-
-%D Seventuple:
-
-\protected\def\doseventupleempty#1%
- {\t_syst_aux{#1}%
- \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop}
-
-\def\syst_helpers_seventuple_empty_one_yes[#1]%
- {\firstargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop}
-
-\def\syst_helpers_seventuple_empty_two_yes[#1]%
- {\secondargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop}
-
-\def\syst_helpers_seventuple_empty_three_yes[#1]%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop}
-
-\def\syst_helpers_seventuple_empty_four_yes[#1]%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop}
-
-\def\syst_helpers_seventuple_empty_five_yes[#1]%
- {\fifthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop}
-
-\def\syst_helpers_seventuple_empty_six_yes[#1]%
- {\sixthargumenttrue
- \toksapp\t_syst_aux{[{#1}]}%
- \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop}
-
-\def\syst_helpers_seventuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][][][]}
-
-\def\syst_helpers_seventuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][][]}
-
-\def\syst_helpers_seventuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][][]}
-
-\def\syst_helpers_seventuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][][]}
-
-\def\syst_helpers_seventuple_empty_five_nop
- {\fifthargumentfalse
- \sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][][]}
-
-\def\syst_helpers_seventuple_empty_six_nop
- {\sixthargumentfalse
- \seventhargumentfalse
- \the\t_syst_aux[][]}
-
-\def\syst_helpers_seventuple_empty_seven_nop
- {\seventhargumentfalse
- \the\t_syst_aux[]}
+% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux}
+% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux}
+%
+% %D Single:
+%
+% \protected\def\dosingleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop}
+%
+% \def\syst_helpers_single_empty_one_nop
+% {\firstargumentfalse
+% \the\t_syst_aux[]}
+%
+% %D Double
+%
+% \protected\def\dodoubleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop}
+%
+% % \def\syst_helpers_double_empty_one_yes[#1]%
+% % {\firstargumenttrue
+% % \toksapp\t_syst_aux{[{#1}]}%
+% % \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop}
+% %
+% % nicer is:
+%
+% \def\syst_helpers_double_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop}
+%
+% \def\syst_helpers_double_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_double_empty_two_nop
+% {\secondargumentfalse
+% \the\t_syst_aux[]}
+%
+% % Triple
+%
+% \protected\def\dotripleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop}
+%
+% \def\syst_helpers_triple_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop}
+%
+% \def\syst_helpers_triple_empty_two_yes[#+]%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop}
+%
+% \def\syst_helpers_triple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \the\t_syst_aux[][][]}
+%
+% \def\syst_helpers_triple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_triple_empty_three_nop
+% {\thirdargumentfalse
+% \the\t_syst_aux[]}
+%
+% %D Quadruple:
+%
+% \protected\def\doquadrupleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop}
+%
+% \def\syst_helpers_quadruple_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop}
+%
+% \def\syst_helpers_quadruple_empty_two_yes[#+]%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop}
+%
+% \def\syst_helpers_quadruple_empty_three_yes[#+]%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop}
+%
+% \def\syst_helpers_quadruple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux[][][][]}
+%
+% \def\syst_helpers_quadruple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux[][][]}
+%
+% \def\syst_helpers_quadruple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_quadruple_empty_four_nop
+% {\fourthargumentfalse
+% \the\t_syst_aux[]}
+%
+% %D Quintuple:
+%
+% \protected\def\doquintupleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop}
+%
+% \def\syst_helpers_quintuple_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop}
+%
+% \def\syst_helpers_quintuple_empty_two_yes[#+]%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop}
+%
+% \def\syst_helpers_quintuple_empty_three_yes[#+]%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop}
+%
+% \def\syst_helpers_quintuple_empty_four_yes[#+]%
+% {\fourthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop}
+%
+% \def\syst_helpers_quintuple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux[][][][][]}
+%
+% \def\syst_helpers_quintuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux[][][][]}
+%
+% \def\syst_helpers_quintuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux[][][]}
+%
+% \def\syst_helpers_quintuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_quintuple_empty_five_nop
+% {\fifthargumentfalse
+% \the\t_syst_aux[]}
+%
+% %D Sixtuple:
+%
+% \protected\def\dosixtupleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop}
+%
+% \def\syst_helpers_sixtuple_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop}
+%
+% \def\syst_helpers_sixtuple_empty_two_yes[#+]%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop}
+%
+% \def\syst_helpers_sixtuple_empty_three_yes[#+]%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop}
+%
+% \def\syst_helpers_sixtuple_empty_four_yes[#+]%
+% {\fourthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop}
+%
+% \def\syst_helpers_sixtuple_empty_five_yes[#+]%
+% {\fifthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop}
+%
+% \def\syst_helpers_sixtuple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \the\t_syst_aux[][][][][][]}
+%
+% \def\syst_helpers_sixtuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \the\t_syst_aux[][][][][]}
+%
+% \def\syst_helpers_sixtuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \the\t_syst_aux[][][][]}
+%
+% \def\syst_helpers_sixtuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \the\t_syst_aux[][][]}
+%
+% \def\syst_helpers_sixtuple_empty_five_nop
+% {\fifthargumentfalse
+% \sixthargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_sixtuple_empty_six_nop
+% {\sixthargumentfalse
+% \the\t_syst_aux[]}
+%
+% %D Seventuple:
+%
+% \protected\def\doseventupleempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop}
+%
+% \def\syst_helpers_seventuple_empty_one_yes[#+]%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop}
+%
+% \def\syst_helpers_seventuple_empty_two_yes[#+]%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop}
+%
+% \def\syst_helpers_seventuple_empty_three_yes[#+]%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop}
+%
+% \def\syst_helpers_seventuple_empty_four_yes[#+]%
+% {\fourthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop}
+%
+% \def\syst_helpers_seventuple_empty_five_yes[#+]%
+% {\fifthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop}
+%
+% \def\syst_helpers_seventuple_empty_six_yes[#+]%
+% {\sixthargumenttrue
+% \toksapp\t_syst_aux{[#1]}%
+% \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop}
+%
+% \def\syst_helpers_seventuple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][][][][][][]}
+%
+% \def\syst_helpers_seventuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][][][][][]}
+%
+% \def\syst_helpers_seventuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][][][][]}
+%
+% \def\syst_helpers_seventuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][][][]}
+%
+% \def\syst_helpers_seventuple_empty_five_nop
+% {\fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][][]}
+%
+% \def\syst_helpers_seventuple_empty_six_nop
+% {\sixthargumentfalse
+% \seventhargumentfalse
+% \the\t_syst_aux[][]}
+%
+% \def\syst_helpers_seventuple_empty_seven_nop
+% {\seventhargumentfalse
+% \the\t_syst_aux[]}
+
+%tolerant\def\syst_single_empty#1\relax[#+]%
+\tolerant\def\syst_single_empty#1\relax[#2]%
+ {\ifarguments
+ \or\firstargumentfalse
+ \or\firstargumenttrue
+ \fi
+ #1[#2]}
+
+%tolerant\def\syst_double_empty#1\relax[#2]#*[#3]%
+\tolerant\def\syst_double_empty#1\relax[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse
+ \or\firstargumenttrue \secondargumentfalse
+ \or\firstargumenttrue \secondargumenttrue
+ \fi
+ #1[#2][#3]}
+
+%tolerant\def\syst_triple_empty#1\relax[#2]#*[#3]#*[#4]%
+\tolerant\def\syst_triple_empty#1\relax[#+]#*[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue
+ \fi
+ #1[#2][#3][#4]}
+
+%tolerant\def\syst_quadruple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]%
+\tolerant\def\syst_quadruple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue
+ \fi
+ #1[#2][#3][#4][#5]}
+
+%\tolerant\def\syst_quintuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]%
+\tolerant\def\syst_quintuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue
+ \fi
+ #1[#2][#3][#4][#5][#6]}
+
+%tolerant\def\syst_sixtuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]%
+\tolerant\def\syst_sixtuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue
+ \fi
+ #1[#2][#3][#4][#5][#6][#7]}
+
+%tolerant\def\syst_seventuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]#*[#8]%
+\tolerant\def\syst_seventuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse\seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumenttrue
+ \fi
+ #1[#2][#3][#4][#5][#6][#7][#8]}
+
+\permanent\protected\def\dosingleempty #1{\syst_single_empty #1\relax}
+\permanent\protected\def\dodoubleempty #1{\syst_double_empty #1\relax}
+\permanent\protected\def\dotripleempty #1{\syst_triple_empty #1\relax}
+\permanent\protected\def\doquadrupleempty #1{\syst_quadruple_empty #1\relax}
+\permanent\protected\def\doquintupleempty #1{\syst_quintuple_empty #1\relax}
+\permanent\protected\def\dosixtupleempty #1{\syst_sixtuple_empty #1\relax}
+\permanent\protected\def\doseventupleempty#1{\syst_seventuple_empty#1\relax}
%D Aliases:
@@ -2363,157 +2491,213 @@
%D \type {conditional} token. Okay, these macros are not called that often but it
%D saves crap when tracing.
-%D NB: experimental code in cont-exp.mkiv
-
-\protected\def\dosinglegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop}
-
-\def\syst_helpers_single_group_empty_one_nop
- {\firstargumentfalse
- \the\t_syst_aux{}}
-
-\protected\def\dodoublegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop}
-
-\def\syst_helpers_group_double_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop}
-
-\def\syst_helpers_group_double_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \the\t_syst_aux{}{}}
-
-\def\syst_helpers_group_double_empty_two_nop
- {\secondargumentfalse
- \the\t_syst_aux{}}
-
-\protected\def\dotriplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop}
-
-\def\syst_helpers_group_triple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop}
-
-\def\syst_helpers_group_triple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop}
-
-\def\syst_helpers_group_triple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux{}{}{}}
-
-\def\syst_helpers_group_triple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \the\t_syst_aux{}{}}
-
-\def\syst_helpers_group_triple_empty_three_nop
- {\thirdargumentfalse
- \the\t_syst_aux{}}
-
-\protected\def\doquadruplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop}
-
-\def\syst_helpers_group_quadruple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop}
-
-\def\syst_helpers_group_quadruple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop}
-
-\def\syst_helpers_group_quadruple_empty_three_yes#1%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop}
-
-\def\syst_helpers_group_quadruple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}{}{}}
-
-\def\syst_helpers_group_quadruple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}{}}
-
-\def\syst_helpers_group_quadruple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \the\t_syst_aux{}{}}
-
-\def\syst_helpers_group_quadruple_empty_four_nop
- {\fourthargumentfalse
- \the\t_syst_aux{}}
-
-\protected\def\doquintuplegroupempty#1%
- {\t_syst_aux{#1}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop}
-
-\def\syst_helpers_group_quintuple_empty_one_yes#1%
- {\firstargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop}
-
-\def\syst_helpers_group_quintuple_empty_two_yes#1%
- {\secondargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop}
-
-\def\syst_helpers_group_quintuple_empty_three_yes#1%
- {\thirdargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop}
-
-\def\syst_helpers_group_quintuple_empty_four_yes#1%
- {\fourthargumenttrue
- \toksapp\t_syst_aux{{#1}}%
- \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop}
-
-\def\syst_helpers_group_quintuple_empty_one_nop
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}{}{}}
-
-\def\syst_helpers_group_quintuple_empty_two_nop
- {\secondargumentfalse
- \thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}{}}
-
-\def\syst_helpers_group_quintuple_empty_three_nop
- {\thirdargumentfalse
- \fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}{}}
-
-\def\syst_helpers_group_quintuple_empty_four_nop
- {\fourthargumentfalse
- \fifthargumentfalse
- \the\t_syst_aux{}{}}
-
-\def\syst_helpers_group_quintuple_empty_five_nop
- {\fifthargumentfalse
- \the\t_syst_aux{}}
+% \protected\def\dosinglegroupempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop}
+%
+% \def\syst_helpers_single_group_empty_one_nop
+% {\firstargumentfalse
+% \the\t_syst_aux{}}
+%
+% \protected\def\dodoublegroupempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop}
+%
+% % \def\syst_helpers_group_double_empty_one_yes#1%
+% % {\firstargumenttrue
+% % \toksapp\t_syst_aux{{#1}}%
+% % \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop}
+% %
+% % nicer is:
+%
+% \def\syst_helpers_group_double_empty_one_yes#+%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop}
+%
+% \def\syst_helpers_group_double_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \the\t_syst_aux{}{}}
+%
+% \def\syst_helpers_group_double_empty_two_nop
+% {\secondargumentfalse
+% \the\t_syst_aux{}}
+%
+% \protected\def\dotriplegroupempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop}
+%
+% \def\syst_helpers_group_triple_empty_one_yes#+%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop}
+%
+% \def\syst_helpers_group_triple_empty_two_yes#+%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop}
+%
+% \def\syst_helpers_group_triple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \the\t_syst_aux{}{}{}}
+%
+% \def\syst_helpers_group_triple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \the\t_syst_aux{}{}}
+%
+% \def\syst_helpers_group_triple_empty_three_nop
+% {\thirdargumentfalse
+% \the\t_syst_aux{}}
+%
+% \protected\def\doquadruplegroupempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop}
+%
+% \def\syst_helpers_group_quadruple_empty_one_yes#+%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop}
+%
+% \def\syst_helpers_group_quadruple_empty_two_yes#+%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop}
+%
+% \def\syst_helpers_group_quadruple_empty_three_yes#+%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop}
+%
+% \def\syst_helpers_group_quadruple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux{}{}{}{}}
+%
+% \def\syst_helpers_group_quadruple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux{}{}{}}
+%
+% \def\syst_helpers_group_quadruple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \the\t_syst_aux{}{}}
+%
+% \def\syst_helpers_group_quadruple_empty_four_nop
+% {\fourthargumentfalse
+% \the\t_syst_aux{}}
+%
+% \protected\def\doquintuplegroupempty#1%
+% {\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop}
+%
+% \def\syst_helpers_group_quintuple_empty_one_yes#+%
+% {\firstargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop}
+%
+% \def\syst_helpers_group_quintuple_empty_two_yes#+%
+% {\secondargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop}
+%
+% \def\syst_helpers_group_quintuple_empty_three_yes#+%
+% {\thirdargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop}
+%
+% \def\syst_helpers_group_quintuple_empty_four_yes#+%
+% {\fourthargumenttrue
+% \toksapp\t_syst_aux{#1}%
+% \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop}
+%
+% \def\syst_helpers_group_quintuple_empty_one_nop
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux{}{}{}{}{}}
+%
+% \def\syst_helpers_group_quintuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux{}{}{}{}}
+%
+% \def\syst_helpers_group_quintuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux{}{}{}}
+%
+% \def\syst_helpers_group_quintuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \the\t_syst_aux{}{}}
+%
+% \def\syst_helpers_group_quintuple_empty_five_nop
+% {\fifthargumentfalse
+% \the\t_syst_aux{}}
+
+\tolerant\def\syst_single_group_empty#1\relax#_%
+ {\ifarguments
+ \or\firstargumentfalse
+ \or\firstargumenttrue
+ \fi
+ #1#2}
+
+\tolerant\def\syst_double_group_empty#1\relax#_#*#_%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse
+ \or\firstargumenttrue \secondargumentfalse
+ \or\firstargumenttrue \secondargumenttrue
+ \fi
+ #1#2#3}
+
+\tolerant\def\syst_triple_group_empty#1\relax#_#*#_#*#_%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue
+ \fi
+ #1#2#3#4}
+
+\tolerant\def\syst_quadruple_group_empty#1\relax#_#*#_#*#_#*#_%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue
+ \fi
+ #1#2#3#4#5}
+
+\tolerant\def\syst_quintuple_group_empty#1\relax#_#*#_#*#_#*#_#*#_%
+ {\ifarguments
+ \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse
+ \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue
+ \fi
+ #1#2#3#4#5#6}
+
+\permanent\protected\def\dosinglegroupempty #1{\syst_single_group_empty #1\relax}
+\permanent\protected\def\dodoublegroupempty #1{\syst_double_group_empty #1\relax}
+\permanent\protected\def\dotriplegroupempty #1{\syst_triple_group_empty #1\relax}
+\permanent\protected\def\doquadruplegroupempty #1{\syst_quadruple_group_empty #1\relax}
+\permanent\protected\def\doquintuplegroupempty #1{\syst_quintuple_group_empty #1\relax}
%D These macros can explictly take care of spaces, which means that the next
%D definition and calls are valid:
@@ -2542,41 +2726,41 @@
%D The next six macros (dedicated to Taco) can conveniently used to select
%D arguments. Their names explain their functionality.
-\def\firstofoneargument #1{#1}
+\permanent\def\firstofoneargument #1{#1}
-\def\firstoftwoarguments #1#-{#1}
-\def\secondoftwoarguments #-#1{#1}
+\permanent\def\firstoftwoarguments #1#-{#1}
+\permanent\def\secondoftwoarguments #-#1{#1}
-\def\firstofthreearguments #1#-#-{#1}
-\def\secondofthreearguments #-#1#-{#1}
-\def\thirdofthreearguments #-#-#1{#1}
+\permanent\def\firstofthreearguments #1#-#-{#1}
+\permanent\def\secondofthreearguments #-#1#-{#1}
+\permanent\def\thirdofthreearguments #-#-#1{#1}
-\def\firstoffourarguments #1#-#-#-{#1}
-\def\secondoffourarguments #-#1#-#-{#1}
-\def\thirdoffourarguments #-#-#1#-{#1}
-\def\fourthoffourarguments #-#-#-#1{#1}
+\permanent\def\firstoffourarguments #1#-#-#-{#1}
+\permanent\def\secondoffourarguments #-#1#-#-{#1}
+\permanent\def\thirdoffourarguments #-#-#1#-{#1}
+\permanent\def\fourthoffourarguments #-#-#-#1{#1}
-\def\firstoffivearguments #1#-#-#-#-{#1}
-\def\secondoffivearguments #-#1#-#-#-{#1}
-\def\thirdoffivearguments #-#-#1#-#-{#1}
-\def\fourthoffivearguments #-#-#-#1#-{#1}
-\def\fifthoffivearguments #-#-#-#-#1{#1}
+\permanent\def\firstoffivearguments #1#-#-#-#-{#1}
+\permanent\def\secondoffivearguments #-#1#-#-#-{#1}
+\permanent\def\thirdoffivearguments #-#-#1#-#-{#1}
+\permanent\def\fourthoffivearguments #-#-#-#1#-{#1}
+\permanent\def\fifthoffivearguments #-#-#-#-#1{#1}
-\def\firstofsixarguments #1#-#-#-#-#-{#1}
-\def\secondofsixarguments#-#1#-#-#-#-{#1}
-\def\thirdofsixarguments #-#-#1#-#-#-{#1}
-\def\fourthofsixarguments#-#-#-#1#-#-{#1}
-\def\fifthofsixarguments #-#-#-#-#1#-{#1}
-\def\sixthofsixarguments #-#-#-#-#-#1{#1}
+\permanent\def\firstofsixarguments #1#-#-#-#-#-{#1}
+\permanent\def\secondofsixarguments#-#1#-#-#-#-{#1}
+\permanent\def\thirdofsixarguments #-#-#1#-#-#-{#1}
+\permanent\def\fourthofsixarguments#-#-#-#1#-#-{#1}
+\permanent\def\fifthofsixarguments #-#-#-#-#1#-{#1}
+\permanent\def\sixthofsixarguments #-#-#-#-#-#1{#1}
-\protected\def\firstofoneunexpanded #1{#1}
+\permanent\protected\def\firstofoneunexpanded #1{#1}
-\protected\def\firstoftwounexpanded #1#-{#1}
-\protected\def\secondoftwounexpanded #-#1{#1}
+\permanent\protected\def\firstoftwounexpanded #1#-{#1}
+\permanent\protected\def\secondoftwounexpanded #-#1{#1}
-\protected\def\firstofthreeunexpanded #1#-#-{#1}
-\protected\def\secondofthreeunexpanded#-#1#-{#1}
-\protected\def\thirdofthreeunexpanded #-#-#1{#1}
+\permanent\protected\def\firstofthreeunexpanded #1#-#-{#1}
+\permanent\protected\def\secondofthreeunexpanded#-#1#-{#1}
+\permanent\protected\def\thirdofthreeunexpanded #-#-#1{#1}
%D \macros
%D {globalletempty,letempty,
@@ -2627,7 +2811,7 @@
%D string with the macro \type {\statuswidth}.
\setnewconstant\statuswidth 15
-\setnewconstant\statuswrite 128 % \pluscxxviii
+%setnewconstant\statuswrite 128 % \pluscxxviii
\ifdefined\writestring \else
@@ -2671,7 +2855,7 @@
\def\syst_helpers_grab_raw_parameter_next
{\expandafterspaces\syst_helpers_grab_raw_parameter}
-\protected\def\rawgetparameters#1[#2]#-[#3]%
+\protected\def\rawgetparameters#1[#2]#*[#3]%
{\def\m_syst_parameter_n{#2}%
%\expandafterspaces\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments}
\expandafter\expandafterspaces\expandafter\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments}
@@ -2687,15 +2871,15 @@
%D can reset this mechanism with \type {\resetglobal}.
\protected\def\resetglobal
- {\let\redoglobal\relax
- \let\dodoglobal\relax}
+ {\enforced\let\redoglobal\relax
+ \enforced\let\dodoglobal\relax}
\resetglobal
\protected\def\doglobal
{\ifx\redoglobal\relax
- \let\redoglobal\global
- \let\dodoglobal\syst_helpers_dodo_global
+ \enforced\let\redoglobal\global
+ \enforced\let\dodoglobal\syst_helpers_dodo_global
\fi}
\def\syst_helpers_dodo_global
@@ -2706,47 +2890,10 @@
\let\syst_helpers_redo_global\redoglobal}
\def\restoreglobal
- {\let\redoglobal\syst_helpers_redo_global
- \let\dodoglobal\syst_helpers_dodo_global}
+ {\enforced\let\redoglobal\syst_helpers_redo_global
+ \enforced\let\dodoglobal\syst_helpers_dodo_global}
-%D A very useful application of this macro is \type {\newif}, \TEX's fake boolean
-%D type. Not being a primitive, \type {\global} hopelessly fails here. But a slight
-%D adaption of Knuth's original macro permits:
-%D
-%D \starttyping
-%D \doglobal\newif\iftest
-%D \stoptyping
-%D
-%D Of course one can still say:
-%D
-%D \starttyping
-%D \global\testtrue
-%D \global\testfalse
-%D \stoptyping
-%D
-%D Apart from the prefixes, a few more \type {\expandafters} are needed:
-
-% \protected\def\newif#1% uses the original plain \@if
-% {\privatescratchcounter\escapechar
-% \escapechar\minusone
-% \expandafter\expandafter\expandafter
-% \redoglobal\expandafter\expandafter\expandafter
-% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
-% \expandafter\expandafter\expandafter
-% \redoglobal\expandafter\expandafter\expandafter
-% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
-% \dodoglobal\@if#1{false}%
-% \escapechar\privatescratchcounter}
-
-\protected\def\newif#1% see syst-ini.mkiv
- {\let\new_if_saved\newif
- \let\newif\new_if_check
- \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
- \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
- \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname
- \let\newif\new_if_saved}
-
-%D Also new:
+%D Whatever:
\protected\def\define#1%
{\ifdefined#1%
@@ -2792,13 +2939,9 @@
%
% [\test]
-\def\s!unexpanded{unexpanded}
-
\bgroup \obeylines
-\glet\stoptexdefinition\relax
-
-\protected\gdef\starttexdefinition%
+\permanent\protected\gdef\starttexdefinition%
{\bgroup%
\obeylines%
\syst_helpers_start_tex_definition}
@@ -2807,7 +2950,9 @@
{\catcode\endoflineasciicode\ignorecatcode%
\clf_texdefinition_one{#1}}
-\gdef\dostarttexdefinition#1\stoptexdefinition%
+\aliased\glet\stoptexdefinition\relax
+
+\permanent\gdef\dostarttexdefinition#1\stoptexdefinition%
{\egroup%
\clf_texdefinition_two{#1}}
@@ -2815,12 +2960,7 @@
% \protected\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace
-\protected\def\texdefinition#1{\begincsname#1\endcsname}
-
-% This is a first variant, more might be added:
-
-\protected\def\starttexcode{\unprotect}
-\protected\def\stoptexcode {\protect}
+\permanent\protected\def\texdefinition#1{\begincsname#1\endcsname}
%D \macros
%D {newcounter,
@@ -3000,14 +3140,24 @@
\let\recurseaction\relax
\let\recursestring\empty
-\let\syst_helpers_stepwise_next\relax
+% \let\syst_helpers_stepwise_next\relax
+
+% \protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step
+% {\ifnum#1>#2\relax
+% \expandafter\syst_helpers_stepwise_recurse_nop
+% \else
+% \def\recurselevel{#1}%
+% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
+% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
\protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step
{\ifnum#1>#2\relax
- \expandafter\syst_helpers_stepwise_recurse_nop
+ \expandafter\gobblefourarguments
\else
\def\recurselevel{#1}%
- \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
+% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
+% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
+ \doubleexpandafter\syst_helpers_stepwise_recurse_yes
\fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
\protected\def\syst_helpers_stepwise_recurse_yes
@@ -3016,20 +3166,23 @@
\protected\def\syst_helpers_stepwise_reverse#1#2#3% from to step
{\ifnum#1<#2\relax
- \expandafter\syst_helpers_stepwise_recurse_nop
+% \expandafter\syst_helpers_stepwise_recurse_nop
+ \expandafter\gobblefourarguments
\else
\def\recurselevel{#1}%
\innerrecurse#1\relax
\advance\innerrecurse#3\relax
- \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter
- \fi\expandafter{\the\innerrecurse}{#2}{#3}}
+% \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter
+% \fi\expandafter{\the\innerrecurse}{#2}{#3}}
+ \doubleexpandafter\syst_helpers_stepwise_reverse_yes
+ \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
\protected\def\syst_helpers_stepwise_reverse_yes
{\syst_helpers_recurse_content
\syst_helpers_stepwise_reverse}
-\protected\def\syst_helpers_stepwise_exit
- {\syst_helpers_stepwise_recurse_nop\relax}
+% \protected\def\syst_helpers_stepwise_exit
+% {\syst_helpers_stepwise_recurse_nop\relax}
\def\doexpandedrecurse#1#2% user macro (also was \doxprecurse)
{\ifnum#1>\zerocount
@@ -3112,8 +3265,8 @@
\protected\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \globalpushmacro\recurselevel
\globalpushmacro\recurseaction
+ \globalpushmacro\recurselevel
\protected\gdef\recurseaction##1##2{#1}%
\let\endofloop\syst_helpers_loop
\syst_helpers_loop1}% no \plusone else \recurselevel wrong
@@ -3197,32 +3350,54 @@
\globalpopmacro\recurseaction
\global\advance\outerrecurse\minusone}
-\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% \protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% {\global\advance\outerrecurse \plusone
+% \globalpushmacro\recurseaction
+% \globalpushmacro\recurselevel
+% \protected\gdef\recurseaction##1##2{#4}%
+% \normalexpanded{\ifcmpnum#3\zerocount
+% \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's
+% \syst_helpers_stepwise_exit
+% \else
+% \syst_helpers_stepwise_reverse
+% \fi
+% \or
+% \syst_helpers_stepwise_exit
+% \or
+% \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's
+% \syst_helpers_stepwise_exit
+% \else
+% \syst_helpers_stepwise_recurse
+% \fi
+% \fi{\number#1}{\number#2}{\number#3}}%
+% \globalpopmacro\recurselevel
+% \globalpopmacro\recurseaction
+% \global\advance\outerrecurse\minusone}
+
+\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 ... todo: remove unused helpers
{\global\advance\outerrecurse \plusone
- \globalpushmacro\recurselevel
\globalpushmacro\recurseaction
+ \globalpushmacro\recurselevel
\protected\gdef\recurseaction##1##2{#4}%
\normalexpanded{\ifcmpnum#3\zerocount
\ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's
- \syst_helpers_stepwise_exit
+ \doubleexpandafter\gobbletwoarguments
\else
- \syst_helpers_stepwise_reverse
+ \tripleexpandafter\syst_helpers_stepwise_reverse
\fi
\or
- \syst_helpers_stepwise_exit
- \or
- \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's
- \syst_helpers_stepwise_exit
- \else
- \syst_helpers_stepwise_recurse
- \fi
- \fi{\number#1}{\number#2}{\number#3}}%
+ \doubleexpandafter\gobbletwoarguments
+ \orelse\ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's
+ \doubleexpandafter\gobbletwoarguments
+ \else
+ \doubleexpandafter\syst_helpers_stepwise_recurse
+ \fi\normalexpanded{{\number#1}{\number#2}{\number#3}}}%
\globalpopmacro\recurselevel
\globalpopmacro\recurseaction
\global\advance\outerrecurse\minusone}
-\protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0%
- {}
+% \protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0%
+% {}
\newcount\fastloopindex
\newcount\fastloopfinal
@@ -3502,7 +3677,7 @@
\fi}
\protected\def\validassignment #1{\ifhastok={#1}} % can become: {\ifhastok=} as we enforce {}
-\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone}
+\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone} % or use unless
%D In \ETEX\ we can use \type {\detokenize} and gain some speed, but in general far
%D less that 1\% for \type {\convertargument} and nil for \type {\convertcommand}.
@@ -4257,34 +4432,44 @@
\expandafter\gtokspre
\fi#2{#1}}
-\def\syst_helpers_append_toks_indeed
- {\ifx\dodoglobal\relax
- \expandafter\toksapp
- \else
- \resetglobal
- \expandafter\gtoksapp
- \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
-
-\def\syst_helpers_prepend_toks_indeed
- {\ifx\dodoglobal\relax
- \expandafter\tokspre
- \else
- \resetglobal
- \expandafter\gtokspre
- \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
+% \def\syst_helpers_append_toks_indeed
+% {\ifx\dodoglobal\relax
+% \expandafter\toksapp
+% \else
+% \resetglobal
+% \expandafter\gtoksapp
+% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
+%
+% \def\syst_helpers_prepend_toks_indeed
+% {\ifx\dodoglobal\relax
+% \expandafter\tokspre
+% \else
+% \resetglobal
+% \expandafter\gtokspre
+% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch}
+%
+% \protected\def\appendtoksonce#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch{#1}%
+% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else
+% \syst_helpers_append_toks_indeed
+% \fi}
+%
+% \protected\def\prependtoksonce#1\to#2%
+% {\let\m_syst_helpers_scratch#2%
+% \t_syst_helpers_scratch{#1}%
+% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else
+% \syst_helpers_prepend_toks_indeed
+% \fi}
\protected\def\appendtoksonce#1\to#2%
- {\let\m_syst_helpers_scratch#2%
- \t_syst_helpers_scratch{#1}%
- \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else
- \syst_helpers_append_toks_indeed
+ {\ifhasxtoks{#1}#2\else
+ \appendtoks#1\to#2%
\fi}
\protected\def\prependtoksonce#1\to#2%
- {\let\m_syst_helpers_scratch#2%
- \t_syst_helpers_scratch{#1}%
- \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else
- \syst_helpers_prepend_toks_indeed
+ {\ifhasxtoks{#1}{#2}\m_syst_helpers_scratch\else
+ \prependtoks#1\to#2%
\fi}
%D The test macro:
@@ -4681,7 +4866,7 @@
\let\newcommalistelement\empty
-\def\syst_helpers_replace_in_comma_list_step#1%
+\def\syst_helpers_replace_in_comma_list_step#1% we can use #+ here too
{\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax
\ifempty\newcommalistelement\else
\ifempty\m_syst_helpers_comma_list_target
@@ -4803,16 +4988,26 @@
\newcount\c_syst_helpers_swapped
\let \m_syst_helpers_swapped\relax
-\protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped}
-\protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped}
-\protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped}
-\protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped}
+% \protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped}
+% \protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped}
+% \protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped}
+% \protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped}
+
+\aliased\let\swapdimens\swapcsvalues
+\aliased\let\swapskips \swapcsvalues
+\aliased\let\swapcounts\swapcsvalues
+\aliased\let\swapmacros\swapcsvalues
\protected\def\globalswapdimens#1#2{\d_syst_helpers_swapped#1\global#1#2\global#2\d_syst_helpers_swapped}
\protected\def\globalswapskips #1#2{\s_syst_helpers_swapped#1\global#1#2\global#2\s_syst_helpers_swapped}
\protected\def\globalswapcounts#1#2{\c_syst_helpers_swapped#1\global#1#2\global#2\c_syst_helpers_swapped}
\protected\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet#1#2\glet#2\m_syst_helpers_swapped}
+\protected\def\globalswapdimens{\global\swapcsvalues}
+\protected\def\globalswapskips {\global\swapcsvalues}
+\protected\def\globalswapcounts{\global\swapcsvalues}
+\protected\def\globalswapmacros{\global\swapcsvalues}
+
%D \macros
%D {pushmacro,popmacro}
%D
@@ -5084,24 +5279,39 @@
%D \definesomething[alfa,beta,...][variable=...,...]
%D \stoptyping
-\let\m_syst_helpers_with_set_command\empty
-\let\syst_helpers_with_set_step \relax
-
-\def\syst_helpers_with_set_double[#1][#2]%
- {\doifsomething{#1}%
- {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}%
+%% \let\syst_helpers_with_set_step\relax
+%% \let\m_syst_helpers_with_set_command\empty
+%%
+%% \def\syst_helpers_with_set_double[#1][#2]%
+%% {\doifsomething{#1}%
+%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}%
+%% \processcommalist[#1]\syst_helpers_with_set_step}}
+%%
+%% \def\syst_helpers_with_set_triple[#1][#2][#3]%
+%% {\doifsomething{#1}%
+%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}%
+%% \processcommalist[#1]\syst_helpers_with_set_step}}
+%%
+%% \def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command
+%% \def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command
+%%
+%% \def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command
+%% \def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command
+
+\let\syst_helpers_with_set_step\relax % maybe push pop
+
+\permanent\tolerant\protected\def\dodoubleemptywithset#1#*[#2]#*[#3]%
+ {\doifsomething{#2}%
+ {\def\syst_helpers_with_set_step##1{#1[##1][#3]}%
\processcommalist[#1]\syst_helpers_with_set_step}}
-\def\syst_helpers_with_set_triple[#1][#2][#3]%
- {\doifsomething{#1}%
- {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}%
+\permanent\tolerant\protected\def\dotripleemptywithset#1#*[#2]#*[#3]#*[#4]%
+ {\doifsomething{#2}%
+ {\def\syst_helpers_with_set_step##1{#1[##1][#3][#4]}%
\processcommalist[#1]\syst_helpers_with_set_step}}
-\def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command
-\def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command
-
-\def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command
-\def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command
+\let\dodoubleargumentwithset\dodoubleemptywithset
+\let\dotripleargumentwithset\dotripleemptywithset
%D \macros
%D {stripcharacters,stripspaces}
@@ -5243,20 +5453,35 @@
\let\syst_helpers_process_separated_list_step\relax
-\def\syst_helpers_process_separated_list#1]#2[#3]#4%
- {\def\syst_helpers_process_separated_list_step##1##2#3%
+% \def\syst_helpers_process_separated_list#1]#*[#2]#3%
+% {\def\syst_helpers_process_separated_list_step##1##2#2%
+% {\def\m_syst_string_one{##2}% suggested by VZ
+% \if]##1%
+% \let\syst_helpers_process_separated_list_step\relax
+% \orelse\ifx\blankspace\m_syst_string_one
+% #3{##1}%
+% \orelse\if]##2%
+% \let\syst_helpers_process_separated_list_step\relax
+% \else
+% #3{##1##2}%
+% \fi
+% \syst_helpers_process_separated_list_step}%
+% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2}
+
+\def\syst_helpers_process_separated_list#1]#*[#2]#3%
+ {\def\syst_helpers_process_separated_list_step##1##2#2%
{\def\m_syst_string_one{##2}% suggested by VZ
\if]##1%
- \let\syst_helpers_process_separated_list_step\relax
\orelse\ifx\blankspace\m_syst_string_one
- #4{##1}%
+ #3{##1}%
+ \expandafter\syst_helpers_process_separated_list_step
\orelse\if]##2%
- \let\syst_helpers_process_separated_list_step\relax
\else
- #4{##1##2}%
+ #3{##1##2}%
+ \expandafter\syst_helpers_process_separated_list_step
\fi
- \syst_helpers_process_separated_list_step}%
- \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3}
+ }%
+ \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2}
\protected\def\processseparatedlist[%
{\syst_helpers_process_separated_list\relax}
@@ -5655,11 +5880,8 @@
%D
%D These two macros savely grab and dispose two arguments.
-\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty}
-\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty}
-
-\def\syst_helpers_gobble_single_empty [#1]{}
-\def\syst_helpers_gobble_double_empty[#1][#2]{}
+\tolerant\protected\def\dogobblesingleempty [#-]{}
+\tolerant\protected\def\dogobbledoubleempty[#-]#*[#-]{}
\let\gobblesingleempty\dogobblesingleempty % also used
\let\gobbledoubleempty\dogobbledoubleempty % also used
@@ -5872,29 +6094,16 @@
\installsystemnamespace{measure}
-\protected\def\definemeasure
- {\dodoubleargument\syst_helpers_define_measure}
-
-\def\syst_helpers_define_measure[#1][#2]%
- {\expandafter\def\csname\??measure#1\endcsname{#2}}
-
-\protected\def\freezemeasure
- {\dodoubleargument\syst_helpers_freeze_measure}
-
-\def\syst_helpers_freeze_measure[#1][#2]%
- {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}}
+\permanent\tolerant\protected\def\definemeasure[#1]#*[#2]{\expandafter \def\csname\??measure#1\endcsname{#2}}
+\permanent\tolerant\protected\def\freezemeasure[#1]#*[#2]{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}}
-\protected\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way
-\protected\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way
-\protected\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
-\protected\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+\permanent\protected\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way
+\permanent\protected\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way
+\permanent\protected\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+\permanent\protected\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
-\def\measure
- {\the\measured}
-
-\def\measured#1%
- %{\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax}
- {\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+\permanent\def\measure {\the\measured}
+\permanent\def\measured#1{\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
% #2 could be omitted, but we want to support spaces
%
@@ -5909,31 +6118,17 @@
\installsystemnamespace{quantity}
-\protected\def\definequantity
- {\dodoubleargument\syst_helpers_define_quantity}
-
-\def\syst_helpers_define_quantity[#1][#2]%
- {\expandafter\def\csname\??quantity#1\endcsname{#2}}
-
-\protected\def\freezequantity
- {\dodoubleargument\syst_helpers_freeze_quantity}
-
-\def\syst_helpers_freeze_quantity[#1][#2]%
- {\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}}
+\permanent\tolerant\protected\def\definequantity[#1]#*[#2]{\expandafter\def \csname\??quantity#1\endcsname{#2}}
+\permanent\tolerant\protected\def\freezequantity[#1]#*[#2]{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}}
-\protected\def\setquantity #1#2{\expandafter\def \csname\??quantity#1\endcsname{#2}} % quick way
-\protected\def\setgquantity#1#2{\expandafter\gdef\csname\??quantity#1\endcsname{#2}} % quick way
-\protected\def\setequantity#1#2{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way
-\protected\def\setxquantity#1#2{\expandafter\xdef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way
+\permanent\protected\def\setquantity #1#2{\expandafter\def \csname\??quantity#1\endcsname{#2}} % quick way
+\permanent\protected\def\setgquantity#1#2{\expandafter\gdef\csname\??quantity#1\endcsname{#2}} % quick way
+\permanent\protected\def\setequantity#1#2{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way
+\permanent\protected\def\setxquantity#1#2{\expandafter\xdef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way
-\def\quantity
- {\the\quantitied}
-
-\def\quantitied#1%
- {\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
-
-\def\directquantity#1%
- {\the\numexpr#1\relax}
+\permanent\def\quantity {\the\quantitied}
+\permanent\def\quantitied #1{\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
+\permanent\def\directquantity#1{\the\numexpr#1\relax}
% let\quantified\quantitied
@@ -5946,7 +6141,7 @@
%D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}]
%D \stoptyping
-\def\dividedsize#1#2#3% size gap n
+\permanent\def\dividedsize#1#2#3% size gap n
{\dimexpr
\ifnum\dimexpr#1\relax>\plusone
(\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1%
@@ -5958,14 +6153,14 @@
%D
%D This is a dirty one: we simply append a unit and discard it when needed.
-\def\doifelsedimension#1%
+\permanent\def\doifelsedimension#1%
{\ifchkdim#1\or
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\let\doifdimensionelse\doifelsedimension
+\aliased\let\doifdimensionelse\doifelsedimension
%D Ok, here's another one, slower but seldom used. This one scans the text.
%D
@@ -5984,18 +6179,18 @@
%D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR
%D \stoptabulate
-\let\doifelsedimenstring\doifelsedimension
-\let\doifdimenstringelse\doifelsedimenstring
+\aliased\let\doifelsedimenstring\doifelsedimension
+\aliased\let\doifdimenstringelse\doifelsedimenstring
%D \macros
%D {comparedimension,comparedimensioneps}
%D
-%D This is a dirty one: we simply append a unit and discard it when needed.
+%D We no longer use the \MKIV\ dirty trick. These are obsolete anyway.
\newdimen \roundingeps \roundingeps=10sp
\newconstant\compresult
-\def\comparedimension#1#2%
+\permanent\def\comparedimension#1#2%
{\compresult
\ifdim#1<#2%
\zerocount
@@ -6005,7 +6200,7 @@
\plustwo
\fi}
-\def\comparedimensioneps#1#2% todo: use eps feature
+\permanent\def\comparedimensioneps#1#2% todo: use eps feature
{\compresult
\ifdim\dimexpr#1-#2\relax<\roudingeps
\zerocount
@@ -6021,62 +6216,52 @@
% \copycsname xxx\endcsname\csname ..\endcsname
-\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
+\permanent\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
% \letcscsname \crap \csname ..\endcsname
% \letcsnamecs \csname ..\endcsname\crap
% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname
-\protected\def\letcscsname {\expandafter\let\expandafter}
-\protected\def\letcsnamecs {\expandafter\let}
-\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
+\permanent\protected\def\letcscsname {\expandafter\let\expandafter}
+\permanent\protected\def\letcsnamecs {\expandafter\let}
+\permanent\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
% another one, add an item to a commalist
-\protected\def\addvalue#1#2% cs item
+\permanent\protected\def\addvalue#1#2% cs item
{\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi
\normalexpanded{\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}}
-\def\unspaced#1%
- {\syst_helpers_unspaced#1\end}
-
-\def\syst_helpers_unspaced#1%
- {\ifx#1\end
- \expandafter\gobbleoneargument
- \orelse\ifx#1\blankspace
- % go on
- \else
- #1%
- \fi
- \syst_helpers_unspaced}
-
-\protected\def\unspaceargument#1\to#2%
- {\privatescratchcounter\catcode\spaceasciicode
- \catcode\spaceasciicode\ignorecatcode
- \scantextokens{\edef#2{#1}}%
- \catcode\spaceasciicode\privatescratchcounter}
+%D Are these ever used? Anyway, these variants are somewhat more efficient than
+%D the \MKIV variants for larger strings.
-\protected\def\unspaceafter#1#2%
- {\unspaceargument#2\to\ascii
- \expandafter#1\expandafter{\ascii}}
+% A variant:
+%
+% \permanent\def\unspaced#1%
+% {\localcontrolled{\begingroup\catcode\spaceasciicode\ignorecatcode}%
+% \tokenized{#1}%
+% \localcontrolled{\endgroup}}
+%
+% but we can also do this:
-% sometimes handy:
+\permanent\def\unspaced#1%
+ {\tokenized \s!catcodetable \ctdcatcodes {#1}}
-\protected\def\doifelsehasspace#1%
- {\edef\m_syst_string_one{#1}%
- \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax}
+\permanent\protected\def\unspaceargument#1\to#2%
+ {\edef#2{\tokenized \s!catcodetable \ctdcatcodes {#1}}}
-\let\doifhasspaceelse\doifelsehasspace
+\protected\def\unspaceafter#1#2%
+ {\expandafter#1\expandafter{\tokenized \s!catcodetable \ctdcatcodes {#2}}}
-\protected\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax
- {\ifx\m_syst_string_one\space
+\permanent\protected\def\doifelsehasspace#1%
+ {\expandafter\ifhastok\space{#1}%
\expandafter\firstoftwoarguments
- \orelse\ifempty#2%
- \expandafter\secondoftwoarguments
\else
- \expandafter\firstoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
+\aliased\let\doifhasspaceelse\doifelsehasspace
+
% this will replace loadfile once and alike !!! todo
\installsystemnamespace{flag}
@@ -6544,4 +6729,24 @@
{\edef\m_syst_string_one{#1}%
\ifempty\m_syst_string_one}
+%D New (also serves as an example):
+%D
+%D \starttyping
+%D \commandflags\defineframed
+%D \stoptyping
+
+\permanent\def\commandflags#1%
+ {\beginlocalcontrol\begingroup\scratchtoks\emptytoks\donefalse
+ \ifflags#1= \frozenflagcode\etoksapp\scratchtoks{\ifdone \space\fi frozen}\donetrue\fi
+ \ifflags#1=\permanentflagcode\etoksapp\scratchtoks{\ifdone \space\fi permanent}\donetrue\fi
+ \ifflags#1=\immutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi immutable}\donetrue\fi
+ \ifflags#1=\primitiveflagcode\etoksapp\scratchtoks{\ifdone \space\fi primitive}\donetrue\fi
+ \ifflags#1= \mutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi mutable}\donetrue\fi
+ \ifflags#1=\noalignedflagcode\etoksapp\scratchtoks{\ifdone \space\fi noaligned}\donetrue\fi
+ \ifflags#1= \instanceflagcode\etoksapp\scratchtoks{\ifdone \space\fi instance}\donetrue\fi
+ %\ifflags#1= \reservedflagcode\etoksapp\scratchtoks{\ifdone \space\fi reserved}\donetrue\fi
+ \ifflags#1= \tolerantflagcode\etoksapp\scratchtoks{\ifdone \space\fi tolerant}\donetrue\fi
+ \ifflags#1=\protectedflagcode\etoksapp\scratchtoks{\ifdone \space\fi protected}\donetrue\fi
+ \expandafter\endgroup\expandafter\endlocalcontrol\the\scratchtoks}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/syst-con.mkxl b/tex/context/base/mkiv/syst-con.mkxl
index ffff5aab7..ed4a4f3c5 100644
--- a/tex/context/base/mkiv/syst-con.mkxl
+++ b/tex/context/base/mkiv/syst-con.mkxl
@@ -20,40 +20,40 @@
%D In addition to the uppercase hex conversion, as needed in math families, we
%D occasionally need a lowercase one.
-\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax}
-\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax}
-\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax}
-\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax}
+\permanent\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax}
+\permanent\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax}
+\permanent\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax}
+\permanent\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax}
-\let\hexnumber\uchexnumber
+\aliased\let\hexnumber\uchexnumber
%D \macros{octnumber}
%D
%D For \UNICODE\ remapping purposes, we need octal numbers.
-\def\octnumber#1{\clf_octnumber\numexpr#1\relax}
+\permanent\def\octnumber#1{\clf_octnumber\numexpr#1\relax}
%D \macros{hexstringtonumber,octstringtonumber}
%D
%D This macro converts a two character hexadecimal number into a decimal number,
%D thereby taking care of lowercase characters as well.
-\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax}
-\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax}
+\permanent\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax}
+\permanent\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax}
%D \macros{rawcharacter}
%D
%D This macro can be used to produce proper 8 bit characters that we sometimes need
%D in backends and round||trips.
-\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax}
+\permanent\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax}
%D \macros{twodigits, threedigits}
%D
%D These macros provides two or three digits always:
-\def\twodigits #1{\ifnum #1<10 0\fi\number#1}
-\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1}
+\permanent\def\twodigits #1{\ifnum #1<10 0\fi\number#1}
+\permanent\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1}
%D \macros{modulonumber}
%D
@@ -68,25 +68,20 @@
%D have behaved like \TEX's normal\type {\divide}, then the expression could have
%D been somewhat simpler, like \type {#2-(#2/#1)*#1}. This works just as well, but a
%D bit more complex.
-%D
-%D \starttyping
-%D \def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
-%D \stoptyping
-%D
-%D But \unknown\ now we can also do this:
-\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax}
+%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
+%permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax}
%D \macros{setcalculatedsin,setcalculatedcos,setcalculatedtan}
-\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}}
-\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}}
-\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}}
+\permanent\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}}
+\permanent\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}}
+\permanent\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}}
%D \macros{formatted,format}
- \def\formatted#1{\ctxcommand{format(#1)}} % not clf
-\protected\def\format #1{\ctxcommand{format(#1)}} % not clf
+\permanent \def\formatted#1{\ctxcommand{format(#1)}} % not clf
+\permanent\protected\def\format #1{\ctxcommand{format(#1)}} % not clf
%D The \type {\modulatednumber} and \type {\realnumber} macros have been removed.
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 70a467ec5..b1ba9e0f3 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -444,6 +444,8 @@
\chardef \pluseight 8
\chardef \plusnine 9
\chardef \plusten 10
+\chardef \pluseleven 11
+\chardef \plustwelve 12
\chardef \plussixteen 16
\chardef \plusfifty 50
\chardef \plushundred 100
@@ -1137,9 +1139,31 @@
\matheqnogapstep\zerocount % for now
-%D Experiment:
-
-\ifdefined\frozen \else \def\frozen{} \let\normalfrozen\frozen \fi
+%D For as long as we share code between \MKIV\ and \LMTX\ we need these:
+
+\ifdefined\overloadmode \else
+ \newcount\overloadmode
+ %
+ \let\frozen \empty
+ \let\tolerant \empty
+ \let\overloaded\empty
+ \let\aliased \empty
+ \let\permanent \empty
+ \let\immutable \empty
+ \let\mutable \empty
+ \let\instance \empty
+ \let\noaligned \empty
+ \let\enforced \empty
+ %
+ \let\unletfrozen\gobbleoneargument
+ \let\letfrozen \gobbleoneargument
+ \def\letcsname {\expandafter\let \csname}
+ \def\defcsname {\expandafter\def \csname}
+ \def\edefcsname {\expandafter\edef\csname}
+ %
+ \let\pushoverloadmode\relax
+ \let\popoverloadmode\relax
+\fi
%D Now we define a few helpers that we need in a very early stage. We have no
%D message system yet but redundant definitions are fatal anyway.
@@ -1198,4 +1222,8 @@
\let\unvpack\unvbox
\fi
+%D Needed:
+
+\let\nexttoken\relax
+
\protect \endinput
diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl
index 4a6352566..fbce9d780 100644
--- a/tex/context/base/mkiv/syst-ini.mkxl
+++ b/tex/context/base/mkiv/syst-ini.mkxl
@@ -24,57 +24,57 @@
%D but we're prestine and have no macros defined yet. Abstraction also makes it
%D possible to avoid the \type {^^} in the input.
-\chardef\escapecatcode 0
-\chardef\begingroupcatcode 1
-\chardef\endgroupcatcode 2
-\chardef\mathshiftcatcode 3
-\chardef\alignmentcatcode 4
-\chardef\endoflinecatcode 5
-\chardef\parametercatcode 6
-\chardef\superscriptcatcode 7
-\chardef\subscriptcatcode 8
-\chardef\ignorecatcode 9
-\chardef\spacecatcode 10
-\chardef\lettercatcode 11
-\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode
-\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode
-\chardef\commentcatcode 14
-\chardef\invalidcatcode 15
+\immutable\integerdef\escapecatcode 0
+\immutable\integerdef\begingroupcatcode 1
+\immutable\integerdef\endgroupcatcode 2
+\immutable\integerdef\mathshiftcatcode 3
+\immutable\integerdef\alignmentcatcode 4
+\immutable\integerdef\endoflinecatcode 5
+\immutable\integerdef\parametercatcode 6
+\immutable\integerdef\superscriptcatcode 7
+\immutable\integerdef\subscriptcatcode 8
+\immutable\integerdef\ignorecatcode 9
+\immutable\integerdef\spacecatcode 10
+\immutable\integerdef\lettercatcode 11
+\immutable\integerdef\othercatcode 12 % finally obsolete: \let\other \othercatcode
+\immutable\integerdef\activecatcode 13 % finally obsolete: \let\active\activecatcode
+\immutable\integerdef\commentcatcode 14
+\immutable\integerdef\invalidcatcode 15
%chardef\zeroasciicode 0
-\chardef\tabasciicode 9
-\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
-\chardef\formfeedasciicode 12
-\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par
-\chardef\endoffileasciicode 26
-\chardef\spaceasciicode 32
-\chardef\exclamationmarkasciicode 33 % ! used in namespace protection
-\chardef\doublequoteasciicode 34 % "
-\chardef\hashasciicode 35
-\chardef\dollarasciicode 36
-\chardef\commentasciicode 37
-\chardef\ampersandasciicode 38
-\chardef\singlequoteasciicode 39 % '
-\chardef\primeasciicode 39 % '
-\chardef\leftparentasciicode 40
-\chardef\rightparentasciicode 41
-\chardef\commaasciicode 44
-\chardef\hyphenasciicode 45
-\chardef\periodasciicode 46
-\chardef\forwardslashasciicode 47 % /
-\chardef\colonasciicode 58
-\chardef\lessthanasciicode 60 % < used as alternative verbatim {
-\chardef\morethanasciicode 62 % > used as alternative verbatim }
-\chardef\questionmarkasciicode 63 % ? used in namespace protection
-\chardef\atsignasciicode 64 % @ used in namespace protection
-\chardef\backslashasciicode 92 % `\\
-\chardef\circumflexasciicode 94
-\chardef\underscoreasciicode 95
-\chardef\leftbraceasciicode 123 % `\{
-\chardef\barasciicode 124 % `\|
-\chardef\rightbraceasciicode 125 % `\}
-\chardef\tildeasciicode 126 % `\~
-\chardef\delasciicode 127
+\immutable\integerdef\tabasciicode 9
+\immutable\integerdef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
+\immutable\integerdef\formfeedasciicode 12
+\immutable\integerdef\endoflineasciicode 13 % somewhat messy but this can be the active \par
+\immutable\integerdef\endoffileasciicode 26
+\immutable\integerdef\spaceasciicode 32
+\immutable\integerdef\exclamationmarkasciicode 33 % ! used in namespace protection
+\immutable\integerdef\doublequoteasciicode 34 % "
+\immutable\integerdef\hashasciicode 35
+\immutable\integerdef\dollarasciicode 36
+\immutable\integerdef\commentasciicode 37
+\immutable\integerdef\ampersandasciicode 38
+\immutable\integerdef\singlequoteasciicode 39 % '
+\immutable\integerdef\primeasciicode 39 % '
+\immutable\integerdef\leftparentasciicode 40
+\immutable\integerdef\rightparentasciicode 41
+\immutable\integerdef\commaasciicode 44
+\immutable\integerdef\hyphenasciicode 45
+\immutable\integerdef\periodasciicode 46
+\immutable\integerdef\forwardslashasciicode 47 % /
+\immutable\integerdef\colonasciicode 58
+\immutable\integerdef\lessthanasciicode 60 % < used as alternative verbatim {
+\immutable\integerdef\morethanasciicode 62 % > used as alternative verbatim }
+\immutable\integerdef\questionmarkasciicode 63 % ? used in namespace protection
+\immutable\integerdef\atsignasciicode 64 % @ used in namespace protection
+\immutable\integerdef\backslashasciicode 92 % `\\
+\immutable\integerdef\circumflexasciicode 94
+\immutable\integerdef\underscoreasciicode 95
+\immutable\integerdef\leftbraceasciicode 123 % `\{
+\immutable\integerdef\barasciicode 124 % `\|
+\immutable\integerdef\rightbraceasciicode 125 % `\}
+\immutable\integerdef\tildeasciicode 126 % `\~
+\immutable\integerdef\delasciicode 127
%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored
\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space
@@ -94,7 +94,7 @@
\catcode\tildeasciicode \activecatcode % `\~ tilde is active
%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid
-\chardef\statuswrite 128
+\chardef\statuswrite 128 % we need to get rid of this one
%D First we need to initialization the primitives. Because \CONTEXT\ is already a
%D pretty old macro package, we have a couple of issues with respect to primitives.
@@ -140,20 +140,20 @@
function tex.enableprimitives() end % so we kind of protect what's there
}
-\def\space{ }
-\def\empty{}
+\permanent\def\space{ }
+\permanent\def\empty{}
-\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed
-\letcharcode \tildeasciicode \ % tilde
-\letcharcode \spaceasciicode \space % space
+\permanent\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed
+\permanent\letcharcode \tildeasciicode \ % tilde
+\permanent\letcharcode \spaceasciicode \space % space
-\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab
-\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed
-\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return
+\permanent\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab
+\permanent\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed
+\permanent\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return
%D For now:
-\def\gobbleoneargument#1{} % will be defined later on anyway
+\permanent\def\gobbleoneargument#-{} % will be defined later on anyway
%D First we define a simplified version of the \CONTEXT\ protection mechanism.
%D Later we will implement a better variant.
@@ -176,8 +176,8 @@
%D Some pretty important definitions:
-\let\bgroup={
-\let\egroup=}
+\immutable\let\bgroup={
+\immutable\let\egroup=}
%D \macros
%D {normalbgroup,normalgroup}
@@ -207,52 +207,42 @@
%
% will be blocked: \newfamily \newlanguage
-\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change
-\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535
-\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0
-\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023
-\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0
-\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191
-\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128
-\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254
-\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128
-\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255
-\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private
-\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0
-\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023
-
-\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read
-\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write
-\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register
-\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context
-\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert
-\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context
-\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context
-
-\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end
-\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end
-
-\countdef \zerocount = 120 \zerocount = 0
-\countdef \plusone = 121 \plusone = 1
-\countdef \minusone = 122 \minusone = -1
-
-\countdef \normalpagebox = 127 \normalpagebox = 255 % hardcoded in pdftex/xetex
-
-% Only to be used by developers in very special cases!
-
-% \def\lastallocatedcount {\the\c_syst_last_allocated_count}
-% \def\lastallocateddimen {\the\c_syst_last_allocated_dimen}
-% \def\lastallocatedskip {\the\c_syst_last_allocated_skip}
-% \def\lastallocatedmuskip {\the\c_syst_last_allocated_muskip}
-% \def\lastallocatedbox {\the\c_syst_last_allocated_dimen}
-% \def\lastallocatedtoks {\the\c_syst_last_allocated_toks}
-% \def\lastallocatedattribute{\the\c_syst_last_allocated_attribute}
+\permanent\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change
+\permanent\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535
+\permanent\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0
+\permanent\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023
+\permanent\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0
+\permanent\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191
+\permanent\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128
+\permanent\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254
+\permanent\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128
+\permanent\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255
+\permanent\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private
+\permanent\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0
+\permanent\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023
+
+\permanent\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read
+\permanent\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write
+\permanent\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register
+\permanent\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context
+\permanent\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert
+\permanent\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context
+\permanent\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context
+
+\permanent\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end
+\permanent\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end
+
+\immutable\integerdef\zerocount = 0
+\immutable\integerdef\plusone = 1
+\immutable\integerdef\minusone = -1
+
+\immutable\integerdef\normalpagebox = 255 % hardcoded in pdftex/xetex
% A few traditional allocations (these might go):
@@ -270,35 +260,41 @@
%D The allocators share a common helper macro.
-\protected\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register}
-\protected\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register}
-\protected\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register}
-\protected\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register}
-\protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \mathchardef\c_syst_max_allocated_register}
-\protected\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register}
-\protected\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \chardef \c_syst_max_allocated_read}
-\protected\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \chardef \c_syst_max_allocated_write}
-\protected\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \mathchardef\c_syst_max_allocated_register}
-\protected\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert}
+\protected\permanent\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register}
+\protected\permanent\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register}
+\protected\permanent\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register}
+\protected\permanent\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register}
+\protected\permanent\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \integerdef\c_syst_max_allocated_register}
+\protected\permanent\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register}
+\protected\permanent\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \integerdef\c_syst_max_allocated_read}
+\protected\permanent\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \integerdef\c_syst_max_allocated_write}
+\protected\permanent\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \integerdef\c_syst_max_allocated_register}
+\protected\permanent\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert}
+\protected\permanent\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\integerdef\c_syst_max_allocated_language} % not needed in context
+\protected\permanent\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \integerdef\c_syst_max_allocated_family} % not needed in context
-%D We don't need these in \CONTEXT:
+\aliased\let\newfam\newfamily
-\protected\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\chardef \c_syst_max_allocated_language}
-\protected\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \chardef \c_syst_max_allocated_family}
-
-\let\newfam\newfamily
-
-\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might becoem the default
+\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might become the default
% Watch out, for the moment we disable the check for already being defined
% later we will revert this but first all chardefs must be replaced.
-\protected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
-\protected\def\setnewconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
-\protected\def\setconstant {} % dummy, no checking, so it warns
+\protected\def\setconstant {}
\protected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax}
-% maybe setconstant with check
+\protected\def\newconstant#1%
+ {\ifx#1\relax
+ %\writestatus{!!!!!!!!!!}{\string #1 => RELAX}%
+ \unletfrozen#1%
+ \newcount#1%
+ \orelse\ifdefined#1%
+ %\writestatus{!!!!!!!!!!}{\string #1 => DEFINED}%
+ \else
+ \newcount#1%
+ \fi}
+
+\protected\def\setnewconstant#1{\newconstant#1#1}
% %D The next definitions are really needed (in \CONTEXT):
@@ -312,13 +308,13 @@
\ifdefined\writestatus \else
%\protected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}}
- \protected\def\writestatus#1#2{\message{#1: #2}}
+ \frozen\protected\def\writestatus#1#2{\message{#1: #2}}
\fi
\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name
{\ifnum#1<#4\relax
\global\advance#1\plusone
- \global#3#5=#1\relax
+ \permanent\global#3#5=#1\relax
\else
\writestatus{warning}{no room for \string#2\space \string#5\space (max: \number#4)}%
\fi}
@@ -339,24 +335,23 @@
%D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of
%D the more limited \type {\mathchardef}.
-\protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register}
-\protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register}
+% \protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register}
+% \protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register}
%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use
%D the attributes directly but always allocate then first. For instance attribute~0
%D is reserved for special purposes (this might change). Attributes in the range
%D 128-1023 are private and should not be touched.
-\let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
+\permanent\integerdef\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
-\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register}
+% \permanent\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register}
%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force
%D strings instead of tokens that take more memory. It's a trick to trick to force
%D strings. This macro is never used in \CONTEXT.
-%protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
-\protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}}
+\permanent\protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}}
%D \macros
%D {scratchcounter,
@@ -445,78 +440,79 @@
%D More allocations:
-\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt
-\newdimen \zeropoint \zeropoint 0pt
-\newdimen \onepoint \onepoint 1pt
-\newdimen \halfapoint \halfapoint 0.5pt
-\newdimen \maxdimen \maxdimen 16383.99999pt % 1073741823sp
-\newcount \maxcount \maxcount 2147483647
-\newdimen \onebasepoint \onebasepoint 1bp
-\newdimen \scaledpoint \scaledpoint 1sp
-\newdimen \thousandpoint \thousandpoint 1000pt
-\newmuskip\zeromuskip \zeromuskip 0mu
-\newmuskip\onemuskip \onemuskip 1mu
+\newskip \zeroskip \immutable\zeroskip 0pt plus 0pt minus 0pt
+\newdimen \zeropoint \immutable\zeropoint 0pt
+\newdimen \onepoint \immutable\onepoint 1pt
+\newdimen \halfapoint \immutable\halfapoint 0.5pt
+\newdimen \maxdimen \immutable\maxdimen 16383.99999pt % 1073741823sp
+\newcount \maxcount \immutable\maxcount 2147483647
+\newdimen \onebasepoint \immutable\onebasepoint 1bp
+\newdimen \scaledpoint \immutable\scaledpoint 1sp
+\newdimen \thousandpoint \immutable\thousandpoint 1000pt
+\newmuskip\zeromuskip \immutable\zeromuskip 0mu
+\newmuskip\onemuskip \immutable\onemuskip 1mu
-\newmuskip\muquad \muquad 18mu
+\newmuskip\muquad \immutable\muquad 18mu
-\let\points \onepoint
-\let\halfpoint\halfapoint
+\aliased\let\points \onepoint
+\aliased\let\halfpoint\halfapoint
\newtoks \emptytoks
-%D And even more: (todo: countdefs 60+)
-
-%newcount\minusone \minusone -1
-\newcount\minustwo \minustwo -2
-%chardef \zerocount 0
-%chardef \plusone 1
-\chardef \plustwo 2
-\chardef \plusthree 3
-\chardef \plusfour 4
-\chardef \plusfive 5
-\chardef \plussix 6
-\chardef \plusseven 7
-\chardef \pluseight 8
-\chardef \plusnine 9
-\chardef \plusten 10
-\chardef \plussixteen 16
-\chardef \plusfifty 50
-\chardef \plushundred 100
-\chardef \plusonehundred 100
-\chardef \plustwohundred 200
-\chardef \plusfivehundred 500
-\chardef \pluscxxvii 127
-\chardef \pluscxxviii 128
-\chardef \pluscclv 255
-\chardef \pluscclvi 256
-\chardef \plusthousand 1000
-\chardef \plustenthousand 10000
-\chardef \plustwentythousand 20000
-\chardef \medcard 32768
-\chardef \maxcard 65536 % pdftex has less mathchars
-\chardef \maxcardminusone 65535
+%D And even more: (todo: countdefs 60+). Watch out, we need a count for a negative constant
+%D but can use chardefs for positive ones. Actually, because we have plenty of counters we
+%D can also use counts for those.
+
+%permanent\integerdef\minusone -1
+\permanent\integerdef\minustwo -2
+%permanent\integerdef\zerocount 0
+%permanent\integerdef\plusone 1
+\permanent\integerdef\plustwo 2
+\permanent\integerdef\plusthree 3
+\permanent\integerdef\plusfour 4
+\permanent\integerdef\plusfive 5
+\permanent\integerdef\plussix 6
+\permanent\integerdef\plusseven 7
+\permanent\integerdef\pluseight 8
+\permanent\integerdef\plusnine 9
+\permanent\integerdef\plusten 10
+\permanent\integerdef\pluseleven 11
+\permanent\integerdef\plustwelve 12
+\permanent\integerdef\plussixteen 16
+\permanent\integerdef\plusfifty 50
+\permanent\integerdef\plushundred 100
+\permanent\integerdef\plusonehundred 100
+\permanent\integerdef\plustwohundred 200
+\permanent\integerdef\plusfivehundred 500
+\permanent\integerdef\pluscxxvii 127
+\permanent\integerdef\pluscxxviii 128
+\permanent\integerdef\pluscclv 255
+\permanent\integerdef\pluscclvi 256
+\permanent\integerdef\plusthousand 1000
+\permanent\integerdef\plustenthousand 10000
+\permanent\integerdef\plustwentythousand 20000
+\permanent\integerdef\medcard 32768
+\permanent\integerdef\maxcard 65536 % pdftex has less mathchars
+\permanent\integerdef\maxcardminusone 65535
%D \macros
%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded}
%D
%D A few handy shortcuts
-\let\singleexpandafter \expandafter
-\def\doubleexpandafter{\expandafter\expandafter\expandafter}
-\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter}
+\permanent\let\singleexpandafter \expandafter
+\permanent\def\doubleexpandafter{\expandafter\expandafter\expandafter}
+\permanent\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter}
%D We prefer the more readable variant than in plain \TEX. User should only
%D use \type {\emptybox}:
\newbox\voidbox % public
-\let\normalhbox\hbox
-\let\normalvbox\vbox
-
-\def\unvoidbox{\unhbox\voidbox}
-\def\emptybox {\box \voidbox} % used in initializations so no attributes
-\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes
-\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes
+\permanent\def\unvoidbox{\unhbox\voidbox}
+\permanent\def\emptybox {\box \voidbox} % used in initializations so no attributes
+\permanent\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes
+\permanent\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes
\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode
@@ -525,7 +521,7 @@
%D
%D We need this one soon:
-\protected\def\dontcomplain
+\permanent\protected\def\dontcomplain
{\hbadness\plustenthousand
\vbadness\plustenthousand
\hfuzz \maxdimen
@@ -534,20 +530,21 @@
%D Some expected plain variants follow. We don't reuse registers because we
%D don't want clashes.
-\let \p@ \onepoint
-\let \m@ne \minusone
-\let \z@ \zeropoint
-\let \@ne \plusone
-\let \tw@ \plustwo
-\let \thr@@ \plusthree
-\let \sixt@@n \plussixteen
-\let \@cclv \pluscclv
-\let \@cclvi \pluscclvi
-\let \voidb@x \voidbox
-\newtoks \toks@ % \scratchtoks
-
-%D We define \type {\newif} a la plain \TEX, but will redefine it later. As
-%D Knuth says:
+\aliased\let\p@ \onepoint
+\aliased\let\m@ne \minusone
+\aliased\let\z@ \zeropoint
+\aliased\let\@ne \plusone
+\aliased\let\tw@ \plustwo
+\aliased\let\thr@@ \plusthree
+\aliased\let\sixt@@n\plussixteen
+\aliased\let\@cclv \pluscclv
+\aliased\let\@cclvi \pluscclvi
+\aliased\let\voidb@x\voidbox
+
+\newtoks \toks@ %scratchtoks
+
+%D We define \type {\newif} a la plain \TEX, but will redefine it later. As Knuth
+%D says:
%D
%D \startnarrower
%D And here's a different sort of allocation: for example,
@@ -588,19 +585,14 @@
% \protected\def\new_if_cs#1#2%
% {\csname\expandafter\newif\csstring#1#2\endcsname}
%
-% We wrap all into one macro:
+% We wrap all into one macro (the frozen stuff adds 10% runtime):
-\protected\def\newif#1%
- {\let\new_if_saved\newif
- \let\newif\new_if_check
- \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
- \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
- \csname\expandafter\newif\csstring#1false\endcsname
- \let\newif\new_if_saved}
+\permanent\protected\def\newif#1%
+ {\permanent\protected\expandafter\gdef\csname\expandafter\new_if_check\csstring#1true\endcsname {\overloaded\frozen\let#1\iftrue }%
+ \permanent\protected\expandafter\gdef\csname\expandafter\new_if_check\csstring#1false\endcsname{\overloaded\frozen\let#1\iffalse}%
+ \csname\expandafter\new_if_check\csstring#1false\endcsname}
-\bgroup
- \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}}
-\egroup
+\normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}}
%D Let's test this one:
@@ -611,22 +603,22 @@
%D A few shortcuts:
-\protected\def\udef {\protected\def }
-\protected\def\ugdef{\protected\gdef}
-\protected\def\uedef{\protected\edef}
-\protected\def\uxdef{\protected\xdef}
+\permanent\protected\def\udef {\protected\def }
+\permanent\protected\def\ugdef{\protected\gdef}
+\permanent\protected\def\uedef{\protected\edef}
+\permanent\protected\def\uxdef{\protected\xdef}
%D For a while we keep the following, as systems like tikz need it. Best
%D not use that one \CONTEXT.
-\let\active\activecatcode
+\aliased\let\active\activecatcode
%D Constants to be used with \type {\interactionmode}.
-\chardef\batchmodecode \zerocount
-\chardef\nonstopmodecode \plusone
-\chardef\scrollmodecode \plustwo
-\chardef\errorstopmodecode \plusthree
+\permanent\integerdef\batchmodecode \zerocount
+\permanent\integerdef\nonstopmodecode \plusone
+\permanent\integerdef\scrollmodecode \plustwo
+\permanent\integerdef\errorstopmodecode \plusthree
%D Of course we want even bigger log files, so we copied this from the \ETEX\
%D source files.
@@ -646,7 +638,7 @@
% no longer \errorstopmode cf. plain tex 3.141592653
-\protected\def\tracingall
+\permanent\protected\def\tracingall
{\tracingonline \plusone
\tracingcommands \plusthree
\tracingmacros \plustwo
@@ -659,16 +651,18 @@
\tracingnesting \plustwo
\tracingassigns \plustwo
\tracingmath \plusone
+ \tracingalignments\plusone
\showboxbreadth \maxcount
\showboxdepth \maxcount}
-\protected\def\loggingall
+\permanent\protected\def\loggingall
{\tracingall
\tracingonline \zerocount}
-\protected\def\tracingnone
+\permanent\protected\def\tracingnone
{\showboxdepth \plusthree
\showboxbreadth \plusfive
+ \tracingalignments\zerocount
\tracingmath \zerocount
\tracingassigns \zerocount
\tracingnesting \zerocount
@@ -691,31 +685,31 @@
\tracingstats\plusone
-%D Here we also save \type {\input}, more will be saved later.
-
-\ifdefined\normalinput \else \let\normalinput\input \fi
-
-%D We don't like outer commands, and we always want access to the original
-%D \type {\input} primitive.
-
-\let\normalouter\outer \def\outer{} % no longer \relax
+%D This is only used when we load \CONTEXT:
-%D To circumvent dependencies, we can postpone certain initializations to
-%D dumping time, by appending them to the \type {\everydump} token register.
-
-\ifdefined\normaldump \else \let\normaldump\dump \fi
+\permanent\def\pushoverloadmode
+ {\edef\popoverloadmode{\overloadmode\the\overloadmode}%
+ \overloadmode\zerocount}
\newtoks\everydump
-\def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump}
-
-%D The same applies for the startup actions.
+\pushoverloadmode
-\ifdefined\normaleveryjob \else \let\normaleveryjob\everyjob \fi
+\protected\def\dump
+ {\the\everydump
+ \global\everydump\emptytoks
+ \pushoverloadmode
+ \glet\dump\relax
+ \popoverloadmode
+ %let\pushoverloadmode\relax
+ %let\popoverloadmode\relax
+% \tracingall
+ \normaldump}
-\let\everyjob\relax \newtoks\everyjob
+\permanent\protected\def\input
+ {\normalinput}
-\normaleveryjob{\the\everyjob}
+\popoverloadmode
%D \macros
%D {newconditional,
@@ -754,27 +748,27 @@
%D Such an implementation gives problems with nested conditionals. The next
%D implementation is about as fast and just as straightforward:
-\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef
-\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef
+\aliased\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef
+\aliased\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef
-\protected\def\settrue #1{\let#1\conditionaltrue }
-\protected\def\setfalse#1{\let#1\conditionalfalse}
+\permanent\protected\def\settrue #1{\integerdef#1\conditionaltrue }
+\permanent\protected\def\setfalse#1{\integerdef#1\conditionalfalse}
-\protected\def\settruevalue #1{\expandafter\let\csname#1\endcsname\conditionaltrue }
-\protected\def\setfalsevalue#1{\expandafter\let\csname#1\endcsname\conditionalfalse}
+\permanent\protected\def\settruevalue #1{\expandafter\integerdef\csname#1\endcsname\conditionaltrue }
+\permanent\protected\def\setfalsevalue#1{\expandafter\integerdef\csname#1\endcsname\conditionalfalse}
-\let\newconditional\setfalse
-\let\ifconditional \ifcase
+\aliased\let\newconditional\setfalse
+\aliased\let\ifconditional \ifcase
-\let\then\relax % so that we can say: \ifnum1>2\then -)
+\aliased\let\then\relax % so that we can say: \ifnum1>2\then -)
-\def\truecondition {\iftrue}
-\def\falsecondition{\iffalse}
+\permanent\def\truecondition {\iftrue}
+\permanent\def\falsecondition{\iffalse}
% This one has to be unprotected otherwise we get a files-ends-to-soon but it's ok
% as conditions expand anyway.
-\def\quitcondition{\orelse\iffalse}
+\permanent\def\quitcondition{\orelse\iffalse}
%D \macros
%D {newmacro,setnewmacro,newfraction}
@@ -782,13 +776,13 @@
%D Let's be complete and also introduce some definers. These are not mandate
%D but handy for grepping.
-\protected\def\newmacro #1{\let#1\empty}
-\protected\def\setnewmacro#1{\let#1}
+\permanent\protected\def\newmacro #1{\let#1\empty}
+\permanent\protected\def\setnewmacro#1{\let#1}
-\def\!!zerocount{0}
-\def\!!plusone {1}
+\permanent\protected\def\newfraction#1{\let#1\!!plusone}
-\protected\def\newfraction#1{\let#1\!!plusone}
+\def\!!zerocount{0} % later redefined
+\def\!!plusone {1} % later redefined
%D It would be handy to have a primitive \type {\unless\ifcase} because then we
%D could use nicer values. Anyhow, this conditional code used to be in the \type
@@ -804,7 +798,7 @@
%D \ifzeropt \somedimen ... \else ... \fi
%D \stoptyping
-\let\ifzeropt\ifcase
+\aliased\let\ifzeropt\ifcase
% these token list helpers might move to syst-aux.mkiv
%
@@ -815,14 +809,14 @@
\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp
-\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=}
-\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=}
+\permanent\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=}
+\permanent\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=}
% \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}}
% \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}}
-\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=}
-\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=}
+\permanent\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=}
+\permanent\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=}
\def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}}
\def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}}
@@ -830,14 +824,14 @@
\def\syst_toks_append_g {\global\syst_toks_append_l }
\def\syst_toks_prepend_g{\global\syst_toks_prepend_l}
-\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next}
-\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next}
+\permanent\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next}
+\permanent\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next}
\def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp}
\def\syst_toks_add_g{\global\syst_toks_add_l}
-\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes
-\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes
+\permanent\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes
+\permanent\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes
%D \macros
%D {begcsname}
@@ -846,7 +840,7 @@
% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
-\let\begcsname\begincsname
+\aliased\let\begcsname\begincsname
%D Now come a few macros that might be needed in successive loading. We redefine the
%D \type {\par} primitive pretty soon so that we get the equivalents right.
@@ -863,13 +857,13 @@
% {\everypar \emptytoks
% \everyendpar\emptytoks}
-\protected\def\reseteverypar
+\permanent\protected\def\reseteverypar
{\everypar\emptytoks}
-\let\endgraf\par
-\let\endline\cr
+\aliased\let\endgraf\par % plain, a kind of funny name
+%aliased\let\endline\cr % plain, not needed and probably also confusing
-\protected\def\null{\hpack{}}
+\permanent\protected\def\null{\hpack{}}
%D The following two might be overloaded later on but some modules need then
%D earlier. These functionality is reflected in the name and will not change.
@@ -885,8 +879,8 @@
% \obeyspaces\glet =\space%
% \egroup
-\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par}
-\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space}
+\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par } % check if these can be \permanent
+\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} % check if these can be \permanent
% %D A constant:
%
@@ -897,12 +891,12 @@
%D get. Beware: this macro does not support nested loops. We use a namespace
%D prefix \type {@@pln}.
-\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go
+\permanent\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go
%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type
%D {\repeat} skippable (clever trick):
-\let\repeat\fi % so both \loop and \repeat are reserved words!
+\permanent\let\repeat\fi % so both \loop and \repeat are reserved words!
%D The original (no \type {@@pln} there):
%D
@@ -927,12 +921,12 @@
%D Although we don't add pagenumbers yet we alias the default register used
%D for counting pages:
-\countdef\pageno\zerocount \pageno\plusone % first page is number 1
+\permanent\countdef\pageno\zerocount \pageno\plusone % first page is number 1
%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides
%D the value.
-\def\folio{\the\pageno} % kind of expected and therefore reserved
+\permanent\def\folio{\the\pageno} % kind of expected and therefore reserved
%D The following registers are kind of standard and (for the moment) we define
%D them here. This might change.
@@ -948,11 +942,11 @@
%D Sometimes kerns make more sense than glue but we need to be in the
%D right mode:
-\protected\def\vkern {\ifhmode\par \fi\kern}
-\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern}
+\permanent\protected\def\vkern {\ifhmode\par \fi\kern}
+\permanent\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern}
-\protected\def\vpenalty{\ifhmode\par \fi\penalty}
-\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty}
+\permanent\protected\def\vpenalty{\ifhmode\par \fi\penalty}
+\permanent\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty}
%D Again a few kind-of-extensions the core. These come from plain \TEX\ but
%D are probably not used in \CONTEXT.
@@ -960,19 +954,19 @@
\newskip \hideskip \hideskip = -1000pt plus 1fill
\newskip \centering \centering = 0pt plus 1000pt minus 1000pt
-\def\hidewidth % for alignment entries that can stick out
+\permanent\def\hidewidth % for alignment entries that can stick out
{\hskip\hideskip}
-\def\ialign % initialized \halign
+\permanent\def\ialign % initialized \halign
{\everycr\emptytoks
\tabskip\zeroskip
\halign}
\newcount \mscount
-\def\spanomit{\span\omit} % bypass error message
+\permanent\def\spanomit{\span\omit} % bypass error message
-\def\multispan#1%
+\permanent\def\multispan#1%
{\omit
\mscount#1\relax
\loop
@@ -980,30 +974,31 @@
\spanomit \advance\mscount\minusone
\repeat}
-\let\nopdfcompression \relax
-\let\onlypdfobjectcompression\relax
-\let\maximumpdfcompression \relax
-\let\normalpdfcompression \relax
+\let\nopdfcompression \relax % later
+\let\onlypdfobjectcompression\relax % later
+\let\maximumpdfcompression \relax % later
+\let\normalpdfcompression \relax % later
%D Basic status stuff.
-\newif\ifproductionrun
+% \newif\ifproductionrun % already defined
%D For those who expect this \unknown
-\ifx\fmtname \undefined \def\fmtname {ConTeXt Initial TeX} \fi
-\ifx\fmtversion\undefined \def\fmtversion{3.1415926} \fi
+\ifx\fmtname \undefined \immutable\def\fmtname {ConTeXt Initial TeX} \fi
+\ifx\fmtversion\undefined \immutable\def\fmtversion{3.1415926} \fi
%D A few bonus macros:
-\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
-\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
+%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
+\permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax}
+\permanent\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
%D These could be set at the \LUA\ end instead:
-\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}}
-\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}}
-\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}}
+\immutable\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}}
+\immutable\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}}
+\immutable\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}}
%D We have no reason not to enable this:
@@ -1012,12 +1007,12 @@
%D We only can set this one via directives (system.synctex) and we only support
%D the context variant. This will go away completely.
-\newcount\synctex \let\normalsynctex\synctex
+\newcount\synctex % \let\normalsynctex\synctex
%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero.
-\voffset\zeropoint \let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset
-\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset
+% \voffset\zeropoint \overloaded\let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset
+% \hoffset\zeropoint \overloaded\let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset
\matheqnogapstep\zerocount % for now
@@ -1029,37 +1024,54 @@
\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
-\protected\def\installsystemnamespace#1%
+\protected\def\installsystemnamespace#1% will be redefined
{\ifcsname ??#1\endcsname
\immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}%
- \expandafter\normalend
\else
\global\advance\c_syst_helpers_n_of_namespaces\plusone
- \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \immutable\expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
\fi}
%D It makes more sense to have these here:
-\let\normalsuperscript \Usuperscript
-\let\normalsubscript \Usubscript
-\let\normalnosuperscript\Unosuperscript
-\let\normalnosubscript \Unosubscript
-\let\normalstartimath \Ustartmath
-\let\normalstopimath \Ustopmath
-\let\normalstartdmath \Ustartdisplaymath
-\let\normalstopdmath \Ustopdisplaymath
+\aliased\let\normalsuperscript \Usuperscript
+\aliased\let\normalsubscript \Usubscript
+\aliased\let\normalnosuperscript\Unosuperscript
+\aliased\let\normalnosubscript \Unosubscript
+\aliased\let\normalstartimath \Ustartmath
+\aliased\let\normalstopimath \Ustopmath
+\aliased\let\normalstartdmath \Ustartdisplaymath
+\aliased\let\normalstopdmath \Ustopdisplaymath
%D Also better here:
-\def\wildcardsymbol{*}
+\immutable\def\wildcardsymbol{*}
%D For a while we will keep these useless numbers as for instance tikz checks for them:
-\frozen\chardef\eTeXversion 2
-\frozen\def \eTeXrevision {2}
+\immutable\integerdef\eTeXversion 2
+\immutable\def \eTeXrevision {2}
%D Experiment:
\glyphdimensionsmode\plusone
+%D Just in case users use this:
+
+\aliased\let\immediateassign \immediate
+\aliased\let\immediateassigned\localcontrolled
+
+%D Needed:
+
+\mutable\let\nexttoken \relax
+\mutable\let\next \relax
+\mutable\let\nextnext \relax
+\mutable\let\nextnextnext\relax
+
+%D For now here: will get a proper solution
+
+\pushoverloadmode
+\mutable\let\par\par
+\popoverloadmode
+
\protect \endinput
diff --git a/tex/context/base/mkiv/syst-lua.lmt b/tex/context/base/mkiv/syst-lua.lmt
index b1735d44e..673c99ae3 100644
--- a/tex/context/base/mkiv/syst-lua.lmt
+++ b/tex/context/base/mkiv/syst-lua.lmt
@@ -41,10 +41,6 @@ local char_given_code = cmd.char_given
local math_given_code = cmd.math_given
local xmath_given_code = cmd.xmath_given
local some_item_code = cmd.some_item
------ call_code = cmd.call
------ the_code = cmd.the
------ convert_code = cmd.convert
------ lua_expandable_call_code = cmd.lua_expandable_call
local getdimen = tex.getdimen
local getglue = tex.getglue
@@ -410,13 +406,28 @@ do
end,
}
+ local boolean_value = tokens.values.boolean
+
implement {
name = "ifeof",
public = true,
usage = "condition",
- actions = function(prefix)
+ actions = function()
local n = scaninteger()
- return tokens.values.boolean, not channels[n]
+ return boolean_value, not channels[n]
+ end,
+ }
+
+ -- for the moment here:
+
+ local getnest = tex.getnest
+
+ implement {
+ name = "ifmvl",
+ public = true,
+ usage = "condition",
+ actions = function()
+ return boolean_value, getnest("ptr") == 0
end,
}
diff --git a/tex/context/base/mkiv/syst-lua.mkiv b/tex/context/base/mkiv/syst-lua.mkiv
index 6ad8f5a99..f0902eaf5 100644
--- a/tex/context/base/mkiv/syst-lua.mkiv
+++ b/tex/context/base/mkiv/syst-lua.mkiv
@@ -57,8 +57,8 @@
\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}}
-\def\expdoifcommonelse\expdoifelsecommon
-\def\expdoifinsetelse \expdoifelseinset
+\let\expdoifcommonelse\expdoifelsecommon
+\let\expdoifinsetelse \expdoifelseinset
%D We define these here, just in case. This permits \typefile {self} otherwise
%D nested b|/|e sep problems.
diff --git a/tex/context/base/mkiv/syst-lua.mkxl b/tex/context/base/mkiv/syst-lua.mkxl
index d04e78392..615562200 100644
--- a/tex/context/base/mkiv/syst-lua.mkxl
+++ b/tex/context/base/mkiv/syst-lua.mkxl
@@ -15,48 +15,48 @@
\unprotect
-\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}}
-\def\expdoif #1#2{\clf_doifsame {#1}{#2}}
-\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}}
+\permanent\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}}
+\permanent\def\expdoif #1#2{\clf_doifsame {#1}{#2}}
+\permanent\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}}
%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road
%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type
%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see
%D other useful applications.
-\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
-\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
-\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+\permanent\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\permanent\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\permanent\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3
% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5
-\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
-\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}}
+\permanent\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
+\permanent\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}}
-\def\expdoifcommonelse\expdoifelsecommon
-\def\expdoifinsetelse \expdoifelseinset
+\aliased\let\expdoifcommonelse\expdoifelsecommon
+\aliased\let\expdoifinsetelse \expdoifelseinset
%D We define these here, just in case. This permits \typefile {self} otherwise
%D nested b|/|e sep problems.
-\def\luastringsep{===}
+\immutable\def\luastringsep{===}
-\edef\!!bs{[\luastringsep[}
-\edef\!!es{]\luastringsep]}
+\immutable\edef\!!bs{[\luastringsep[}
+\immutable\edef\!!es{]\luastringsep]}
-\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}}
+\permanent\overloaded\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}}
%D We can omit the tex.ctxcatcodes here as nowadays we seldom change the regime at
%D the \TEX\ end:
%def\luaexpr#1{\ctxlua{context (tostring(#1))}} % more efficient:
-\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled
+\permanent\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled
%D But as we only use write 16 we could as well do all in \LUA\ and ignore the rest.
%D Okay, we still can do writes here but only when not blocked.
-\let\syst_write_execute\clf_execute % always {...}
+\aliased\let\syst_write_execute\clf_execute % always {...}
%D There is a probably rather useless \type {\expression} command that can mix \LUA\ numeric
%D expressions with \TEX\ commands (for as far that makes sense) that works like this:
diff --git a/tex/context/base/mkiv/syst-mac.lmt b/tex/context/base/mkiv/syst-mac.lmt
index 6fc8df2a4..410a49f8b 100644
--- a/tex/context/base/mkiv/syst-mac.lmt
+++ b/tex/context/base/mkiv/syst-mac.lmt
@@ -35,7 +35,7 @@ local function pushmacro(name,global)
if s then
insert(stack[name],s)
else
- report("no macro %a",name)
+ report("no macro %a to push",name)
insert(stack[name],false)
end
end
@@ -45,7 +45,7 @@ local function popmacro(name)
if s then
pop_macro(s)
else
- -- error
+ report("no macro %a to pop",name)
end
end
diff --git a/tex/context/base/mkiv/syst-mes.mkiv b/tex/context/base/mkiv/syst-mes.mkiv
index cf9da21de..ff7ab1ce3 100644
--- a/tex/context/base/mkiv/syst-mes.mkiv
+++ b/tex/context/base/mkiv/syst-mes.mkiv
@@ -11,8 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\protected\def\writestring {\immediate\write\statuswrite}
-\protected\def\writeline {\writestring{}}
- \let\message \normalmessage
+\protected\def\writestring{\immediate\write\statuswrite}
+\protected\def\writeline {\writestring{}}
+% \let\message \normalmessage
\endinput
diff --git a/tex/context/base/mkiv/tabl-com.mkxl b/tex/context/base/mkiv/tabl-com.mkxl
new file mode 100644
index 000000000..c6a0c14bc
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-com.mkxl
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=tabl-com,
+%D version=2009.08.22,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Common Code,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Common Code}
+
+\unprotect
+
+\pushoverloadmode
+
+\permanent\let\AR\relax
+\permanent\let\BA\relax
+\permanent\let\BC\relax
+\permanent\let\BL\relax
+\permanent\let\CC\relax
+\permanent\let\CL\relax
+\permanent\let\CM\relax
+\permanent\let\CR\relax
+\permanent\let\DB\relax
+\permanent\let\EQ\relax
+\permanent\let\FB\relax
+\permanent\let\FL\relax
+\permanent\let\FR\relax
+\permanent\let\HC\relax
+\permanent\let\HL\relax
+\permanent\let\HQ\relax
+\permanent\let\HR\relax
+\permanent\let\LB\relax
+\permanent\let\LL\relax
+\permanent\let\LR\relax
+\permanent\let\ML\relax
+\permanent\let\MR\relax
+\permanent\let\NA\relax
+\permanent\let\NB\relax
+\permanent\let\NC\relax
+\permanent\let\ND\relax
+\permanent\let\NF\relax
+\permanent\let\NG\relax
+\permanent\let\NI\relax
+\permanent\let\NL\relax
+\permanent\let\NN\relax
+\permanent\let\NP\relax
+\permanent\let\NR\relax
+\permanent\let\PB\relax
+\permanent\let\RC\relax
+\permanent\let\RQ\relax
+\permanent\let\SR\relax
+\permanent\let\TL\relax
+\permanent\let\VL\relax
+
+\popoverloadmode
+
+\installmacrostack\BC
+\installmacrostack\EC
+\installmacrostack\EQ
+\installmacrostack\NC
+\installmacrostack\NN
+\installmacrostack\NR
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-frm.mkxl b/tex/context/base/mkiv/tabl-frm.mkxl
new file mode 100644
index 000000000..5cafec76a
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-frm.mkxl
@@ -0,0 +1,261 @@
+%D \module
+%D [ file=tabl-frm,
+%D version=2017.04.11,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Framed Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D For Thomas Schmitz who needed 3000 pages long tables.
+
+\unprotect
+
+\writestatus{loading}{ConTeXt Table Macros / Framed Tables}
+
+\installcorenamespace{framedtable}
+\installcorenamespace{framedtablerow}
+\installcorenamespace{framedtablecolumn}
+
+\newcount\c_tabl_framed_c
+\newcount\c_tabl_framed_r
+\newdimen\d_tabl_framed_h
+\newdimen\d_tabl_framed_d
+\newdimen\b_tabl_framed
+
+\initializeboxstack\??framedtable
+
+\defineframed[\??framedtable]
+\defineframed[\??framedtablerow][\??framedtable]
+\defineframed[\??framedtablecolumn][\??framedtable]
+
+\setupframed
+ [\??framedtable]
+ [\c!distance=\zeropoint,
+ \c!before=,
+ \c!after=,
+ \c!inbetween=]
+
+\setupframed
+ [\??framedtablerow]
+ [\c!strut=\v!no,
+ \c!offset=\v!overlay]
+
+% \defineframedtable[foo]
+% \defineframedtable[bar][foo]
+
+\permanent\tolerant\protected\def\defineframedtable[#1]#*[#2]%
+ {\ifarguments\or
+ \defineframed[\??framedtable#1][\??framedtable]%
+ \or
+ \defineframed[\??framedtable#1][\??framedtable#2]%
+ \fi}
+
+% \setupframedtable[foo][...]
+
+\permanent\tolerant\protected\def\setupframedtable[#1]#*[#2]%
+ {\ifarguments\or
+ \setupframed[\??framedtable][#1]%
+ \or
+ \ifcsname\??framed:\??framedtable#1\endcsname \else
+ \defineframed[\??framedtable#1][\??framedtable]%
+ \fi
+ \setupframed[\??framedtable#1][#2]%
+ \fi}
+
+% \setupframedtable[1][...]
+% \setupframedtable[foo][1][...]
+
+\permanent\tolerant\protected\def\setupframedtablerow[#1]#*[#2]#*[#3]%
+ {\ifarguments\or\or
+ \ifcsname\??framed:\??framedtablerow:#1\endcsname \else
+ \defineframed[\??framedtablerow:#1][\??framedtable]%
+ \fi
+ \setupframed[\??framedtablerow:#1][#2]%
+ \or
+ \ifcsname\??framed:\??framedtable#1\endcsname \else
+ \defineframed[\??framedtable#1][\??framedtable]%
+ \fi
+ \ifcsname\??framed:\??framedtablerow#1:#2\endcsname \else
+ \defineframed[\??framedtablerow#1:#2][\??framedtable#1]%
+ \fi
+ \setupframed[\??framedtablerow#1:#2][#3]%
+ \fi}
+
+\permanent\tolerant\protected\def\setupframedtablecolumn[#1]#*[#2]#*[#3]%
+ {\ifarguments\or\or
+ \ifcsname\??framed:\??framedtablecolumn:#1\endcsname \else
+ \defineframed[\??framedtablecolumn:#1][\??framedtable]%
+ \fi
+ \setupframed[\??framedtablecolumn:#1][#2]%
+ \or
+ \ifcsname\??framed:\??framedtable#1\endcsname \else
+ \defineframed[\??framedtable#1][\??framedtable]%
+ \fi
+ \ifcsname\??framed:\??framedtablecolumn#1:#2\endcsname \else
+ \defineframed[\??framedtablecolumn#1:#2][\??framedtable#1]%
+ \fi
+ \setupframed[\??framedtablecolumn#1:#2][#3]%
+ \fi}
+
+\permanent\tolerant\protected\def\startframedtable[#1]#*[#2]%
+ {\begingroup
+ \forgetall
+ \ifhastok={#1}%
+ \let\currentframedtable\empty
+ \setupframed[\??framedtable][#1]%
+ \else
+ \edef\currentframedtable{#1}%
+ \setupframed[\??framedtable][#2]%
+ \fi
+ \edef\currentframed{\??framedtable\currentframedtable}%
+ \c_tabl_framed_r\zerocount
+ \d_tabl_framed_d\framedparameter\c!distance
+ \framedparameter\c!before}
+
+\permanent\protected\def\stopframedtable
+ {\framedparameter\c!after
+ \endgroup}
+
+% a two pass variant that deals with the height .. so no catcode changes here
+
+\tolerant\protected\def\pack_framed_start_framed_whatever[#1]%
+ {\pack_framed_initialize
+ \bgroup
+ \setupcurrentframed[#1]% here !
+ \pack_framed_process_indeed
+ \bgroup
+ \ignorespaces}
+
+% \permanent\protected\def\startframedrow
+% {\advance\c_tabl_framed_r\plusone
+% \c_tabl_framed_c\zerocount
+% \d_tabl_framed_h\zeropoint
+% \bgroup
+% \edef\currentframed{\number\c_tabl_framed_r}%
+% \edef\currentframed
+% {\??framedtablerow\currentframedtable
+% \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname
+% :\currentframed
+% \else\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname
+% :\v!each
+% \fi\fi}%
+% \pack_framed_start_framed_whatever}
+%
+% \permanent\protected\def\stopframedrow
+% {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row
+% \stopframed
+% \nointerlineskip
+% \vskip\zeropoint\relax
+% \framedparameter\c!inbetween}
+
+\protected\def\tabl_framed_flush_row
+ {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}%
+ \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi}
+
+\newcount\c_tabl_framed_pass
+
+\permanent\let\stopframedrow\relax
+
+\permanent\protected\def\startframedrow#1\stopframedrow
+ {\advance\c_tabl_framed_r\plusone
+ \startframedrow_one#1\stopframedrow_one
+ \startframedrow_two#1\stopframedrow_two}
+
+\tolerant\def\startframedrow_one[#-]%
+ {\bgroup
+ \c_tabl_framed_pass\plusone
+ \c_tabl_framed_c\zerocount
+ \d_tabl_framed_h\zeropoint
+ \settrialtypesetting}
+
+\protected\def\stopframedrow_one
+ {\normalexpanded{\egroup\d_tabl_framed_h\the\d_tabl_framed_h\relax}}
+
+\def\startframedrow_two
+ {\bgroup
+ \c_tabl_framed_c\zerocount
+ \c_tabl_framed_pass\plustwo
+ \edef\currentframed{\number\c_tabl_framed_r}%
+ \edef\currentframed
+ {\??framedtablerow\currentframedtable
+ \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname
+ :\currentframed
+ \else\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname
+ :\v!each
+ \fi\fi}%
+ \pack_framed_start_framed_whatever}
+
+\protected\def\stopframedrow_two
+ {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row
+ \stopframed
+ \nointerlineskip
+ \vskip\zeropoint\relax
+ \framedparameter\c!inbetween}
+
+\protected\def\tabl_framed_flush_row_two
+ {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}%
+ \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi}
+
+\permanent\protected\def\startframedcell
+ {\advance\c_tabl_framed_c\plusone
+ \setbox\b_tabl_framed\hpack\bgroup
+ %\bgroup
+ \edef\currentframed{\number\c_tabl_framed_c}%
+ \edef\currentframed
+ {\??framedtablecolumn\currentframedtable
+ \ifcsname\??framedtablecolumn\currentframedtable:\currentframed\endcsname
+ :\currentframed
+ \else\ifcsname\??framedtablecolumn\currentframedtable:\v!each\endcsname
+ :\v!each
+ \fi\fi}%
+ \ifcase\c_tabl_framed_pass
+ \or
+ \letframedparameter\c!background\empty
+ \letframedparameter\c!frame\v!off
+ \or
+ \letframedparameter\c!height\d_tabl_framed_h
+ \fi
+ \pack_framed_start_framed_whatever}
+
+\permanent\protected\def\stopframedcell
+ {\stopframed
+ %\egroup
+ \ifcase\c_tabl_framed_pass
+ \or
+ \ifdim\ht\b_tabl_framed>\d_tabl_framed_h
+ \d_tabl_framed_h\ht\b_tabl_framed
+ \fi
+ \else
+ \savebox\??framedtable{\number\c_tabl_framed_c}{\box\b_tabl_framed}%
+ \fi}
+
+\protect \endinput
+
+\starttext
+
+\setupframedtablecolumn [1] [width=3cm,background=color,backgroundcolor=red]
+\setupframedtablecolumn [2] [width=4cm,background=color,backgroundcolor=green,align=normal]
+% \setupframedtablerow [each] [background=color,backgroundcolor=blue,strut=no]
+% \setupframedtablerow [each] [strut=no,offset=overlay]
+
+\startframedtable[inbetween=\kern-0.4pt,distance=-0.4pt]
+
+\testfeatureonce{10000}{
+% \testfeatureonce{10}{
+ \startframedrow
+ \startframedcell%[backgroundcolor=yellow]
+ test
+ \stopframedcell
+ \startframedcell
+ test \par test
+ \stopframedcell
+ \stopframedrow
+}
+\stopframedtable
+
+\stoptext
diff --git a/tex/context/base/mkiv/tabl-ltb.mkxl b/tex/context/base/mkiv/tabl-ltb.mkxl
new file mode 100644
index 000000000..b72c5c7d6
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-ltb.mkxl
@@ -0,0 +1,813 @@
+%D \module
+%D [ file=tabl-ltb,
+%D version=2002.10.31, % updated 2016.01.08
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Line Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module was made for some special project where we needed to typeset tables
+%D spanning spanning many pages horizontally and vertically, with repeated header
+%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a
+%D table, which is why the table can go into a buffer or file. As said, tables can
+%D be real huge but performance is still quite okay (there is room for some speed
+%D up). The code has been adapted to \MKIV\ but the functionality is the same as in
+%D \MKII.
+
+% \BH \BC .. \EC \BC .. \EC \EH % append
+% \BR \BC .. \EC \BC .. \EC \ER
+%
+% or
+%
+% \NC .. \NC .. \NC \NR (todo: optional last \NC)
+
+% alternative:
+%
+% (1) direct run, save content in macro, but only if needed
+%
+% todo
+%
+% (2) buffered table content
+%
+% \startbuffer
+% \startlinetablehead
+% \stoplinetablehead
+% \startlinetablebody
+% \stoplinetablebody
+% \stopbuffer
+%
+% \processlinetablebuffer[buffer]
+%
+% in buffer : head and body
+%
+% (3) unbuffered run, multipass
+%
+% - run with starting width zero / prev run
+% - clip on prev run
+% - flush real widths
+
+\writestatus{loading}{ConTeXt Table Macros / Line Tables}
+
+\unprotect
+
+\installcorenamespace{linetable}
+\installcorenamespace{linetablepart}
+\installcorenamespace{linetablewidth}
+\installcorenamespace{linetableheight}
+\installcorenamespace{linetabledepth}
+
+\newconditional \c_tabl_lines_preroll
+\newconditional \c_tabl_lines_in_table
+
+\newdimen \d_tabl_lines_width
+\newdimen \d_tabl_lines_height
+%newdimen \d_tabl_lines_depth
+
+\newbox \b_tabl_lines_cell
+
+\newcount \c_tabl_lines_n_of_columns
+\newcount \c_tabl_lines_n_of_rows
+\newcount \c_tabl_lines_n_of_lines
+\newcount \c_tabl_lines_n_of_parts
+\newcount \c_tabl_lines_part \c_tabl_lines_part\plusone
+\newcount \c_tabl_lines_step \c_tabl_lines_step\plusone
+\newcount \c_tabl_lines_line
+\newcount \c_tabl_lines_row
+\newcount \c_tabl_lines_rows
+\newcount \c_tabl_lines_column
+\newcount \c_tabl_lines_subcol
+
+\newconstant \c_tabl_lines_hmode
+\newconstant \c_tabl_lines_page
+\newconstant \c_tabl_lines_repeat
+\newconstant \c_tabl_lines_split_state
+\newconstant \c_tabl_lines_head_state
+\newconstant \c_tabl_lines_mode
+
+\newtoks \t_tabl_lines_head
+
+\newconditional \linetableautoheight \settrue\linetableautoheight
+
+\initializetablebox\zerocount % holds repeater
+
+\pushoverloadmode
+
+\permanent\tolerant\protected\def\setuplinetable[#1]#*[#2]#*[#3]%
+ {\ifarguments\or
+ \getparameters[\??linetable][#1]%
+ \or
+ \getparameters[\??linetable#1:][#2]%
+ \or
+ \getparameters[\??linetable#1:#2][#3]%
+ \fi}
+
+\permanent\def\linetableparameter#1%
+ {\begincsname\??linetable#1\endcsname}
+
+\permanent\protected\def\doifelselinetablecparameter#1%
+ {\ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??linetable c:#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\aliased\let\doiflinetablecparameterelse\doifelselinetablecparameter
+
+\permanent\def\linetablecparameter#1%
+ {\begincsname
+ \??linetable
+ \ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname
+ c:\number\c_tabl_lines_column
+ \else\ifcsname\??linetable c:#1\endcsname
+ c:%
+ \fi\fi
+ #1%
+ \endcsname}
+
+\permanent\def\linetablerparameter#1% faster, leaner and meaner
+ {\begincsname
+ \??linetable
+ \ifnum\c_tabl_lines_row=\zerocount % geen ifcase
+ \ifcsname\??linetable r:\v!header#1\endcsname
+ r:\v!header
+ \else\ifcsname\??linetable r:0#1\endcsname
+ r:0%
+ \fi\fi
+ \else
+ \ifcsname\??linetable r:\number\c_tabl_lines_row#1\endcsname
+ r:\number\c_tabl_lines_row
+ \else\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname
+ r:\v!oddeven\c_tabl_lines_row
+ \fi\fi
+ \fi
+ #1%
+ \endcsname}
+
+\protected\def\tabl_lines_set
+ {\edef\p_lines{\linetableparameter\c!lines}%
+ \ifx\p_lines\v!fit
+ \tabl_lines_set_indeed
+ \else
+ \global\c_tabl_lines_n_of_lines\p_lines
+ \fi}
+
+\protected\def\tabl_lines_set_indeed
+ {% whitespace already added by vertical strut
+ %\triggerpagebuilder
+ \scratchdimen
+ \ifdim\pagegoal<\maxdimen
+ \dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \textheight
+ \fi
+ \getrawnoflines\scratchdimen
+ \global\c_tabl_lines_n_of_lines\noflines
+ \ifconditional\c_tabl_lines_preroll \else \ifnum\c_tabl_lines_n_of_lines<\plustwo
+ \page
+ \tabl_lines_set
+ \fi \fi}
+
+\def\tabl_lines_step_cell
+ {\advance\scratchdimen\linetablecparameter\c!width
+ \global\advance \c_tabl_lines_column\plusone
+ \advance\scratchskip \linetablecparameter\c!distance}
+
+\permanent\tolerant\protected\def\startlinetablecell[#1]%
+ {\global\setbox\b_tabl_lines_cell\hbox\bgroup
+ \ifparameter#1\or
+ \getparameters[\??linetable c:\number\c_tabl_lines_column][#1]%
+ \fi
+ \global\c_tabl_lines_step\linetablecparameter\c!nx\relax
+ \ifcase\c_tabl_lines_step\or
+ \scratchdimen\linetablecparameter\c!width
+ \scratchskip \linetablecparameter\c!distance
+ \else
+ \scratchdimen \zeropoint
+ \scratchskip \zeropoint
+ \scratchcounter\c_tabl_lines_column
+ \dorecurse\c_tabl_lines_step\tabl_lines_step_cell
+ \global\c_tabl_lines_column\scratchcounter
+ \fi
+ \c_tabl_lines_mode
+ \ifconditional\c_tabl_lines_preroll
+ \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi
+ \else
+ \zerocount
+ \fi
+ \ifcase\c_tabl_lines_mode
+ \ifcase\c_tabl_lines_hmode
+ % nothing
+ \or
+ % fit, keep it simple
+ \or
+ \c_tabl_lines_mode\plusone % line
+ \else
+ % some already calculated height
+ \fi
+ \fi
+ \setbox\scratchbox\hbox
+ \bgroup
+ \dontcomplain
+ \hskip\linetablecparameter\c!leftoffset\relax
+ % 0 = width, unknown height
+ % 1 = width, fixed height
+ % 2 = no width, auto hsize
+ \ifnum\c_tabl_lines_mode<\plustwo
+ \advance\scratchdimen-\linetablecparameter\c!leftoffset
+ \advance\scratchdimen-\linetablecparameter\c!rightoffset
+ \fi
+ \ifcase\c_tabl_lines_mode
+ \dosetraggedcommand{\linetablecparameter\c!align}%
+ \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup
+ \hsize\scratchdimen
+ \raggedcommand
+ \else
+ \setalignmentswitch{\linetablecparameter\c!align}%
+ \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup
+ \ifcase\alignmentswitch\hss\or\hss\fi
+ \fi
+ \dousestyleparameter{\linetablecparameter\c!style}%
+ \dousecolorparameter{\linetablecparameter\c!color}%
+ \begstrut \ignorespaces}
+
+\permanent\protected\def\stoplinetablecell
+ {\unskip \endstrut
+ \ifcase\c_tabl_lines_mode
+ \endgraf
+ \else
+ \ifcase\alignmentswitch\else\hss\fi
+ \fi
+ \egroup
+ \hskip\linetablecparameter\c!rightoffset
+ \egroup
+ \ifconditional\c_tabl_lines_preroll
+ \box\scratchbox
+ \else
+ \tabl_lines_wrap_up
+ \fi
+ \egroup}
+
+\def\tabl_lines_wrap_up
+ {\edef\p_background{\linetablecparameter\c!background}%
+ \ifx\p_background\v!color
+ \ifconditional\linetableautoheight
+ \tabl_lines_wrap_up_auto
+ \else
+ \tabl_lines_wrap_up_line
+ \fi
+ \else
+ \box\scratchbox
+ \fi}
+
+% \startuseMPgraphic{one}
+% path p, q ;
+% numeric r ;
+% r := RuleThickness ;
+% p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ;
+% q := p topenlarged -r bottomenlarged -r ;
+% draw q ;
+% setbounds currentpicture to p;
+% \stopuseMPgraphic
+%
+% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt]
+% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt]
+%
+% \startlinetable
+% \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
+% \stoplinetable
+
+\def\tabl_lines_wrap_up_auto
+ {\edef\p_height{\linetablerparameter{x\c!height}}%
+ \edef\p_depth {\linetablerparameter{x\c!depth }}%
+ \hpack
+ {\blackrule
+ [ \c!color=\linetablecparameter\c!backgroundcolor,
+ \c!type=\linetablecparameter\c!type,
+ \c!mp=\linetablecparameter\c!mp,
+ \c!rulethickness=\linetablecparameter\c!rulethickness,
+ \c!height=\ifx\p_height\empty\ht\scratchbox\else\p_height\fi,
+ \c!depth=\ifx\p_depth \empty\dp\scratchbox\else\p_depth \fi,
+ \c!width=\wd\scratchbox]%
+ \hskip-\wd\scratchbox\box\scratchbox}}
+
+\def\tabl_lines_wrap_up_auto_r
+ {\hpack
+ {\blackrule
+ [ \c!color=\linetablerparameter\c!backgroundcolor,
+ \c!type=\linetablerparameter\c!type,
+ \c!mp=\linetablerparameter\c!mp,
+ \c!rulethickness=\linetablerparameter\c!rulethickness,
+ \c!height=\ht\scratchbox,
+ \c!depth=\dp\scratchbox,
+ \c!width=\wd\scratchbox]%
+ \hskip-\wd\scratchbox\box\scratchbox}}
+
+\def\tabl_lines_wrap_up_line
+ {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}}
+
+\def\tabl_lines_save_part
+ {\global\setbox\tablebox\c_tabl_lines_part
+ \ifcase\c_tabl_lines_part\relax
+ \box\scratchbox % just storing
+ \else
+ \vbox
+ {\ifvoid\tablebox\c_tabl_lines_part\else\unvbox\tablebox\c_tabl_lines_part\fi
+ \edef\p_background{\linetablerparameter\c!background}%
+ \ifx\p_background\v!color
+ \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}%
+ \else
+ \edef\p_type{\linetablerparameter\c!type}%
+ \ifx\p_type\empty
+ \box\scratchbox
+ \else
+ \tabl_lines_wrap_up_auto_r
+ \fi
+ \fi
+ \endgraf
+ \linetablerparameter\c!after}%
+ \fi}
+
+\def\tabl_lines_flush_parts
+ {\global\advance\c_tabl_lines_line\plusone
+ \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines
+ % keep collecting
+ \else
+ \ifconditional\c_tabl_lines_preroll
+ % forget about them
+ \else
+ \dorecurse\c_tabl_lines_n_of_parts
+ {\c_tabl_lines_part\recurselevel
+ \dp\tablebox\c_tabl_lines_part\strutdepth
+ % noindent en endgraf needed else whitespace mess-up!
+ \whitespace % here not after verticalstrut
+ \ifdim\topskipgap=\zeropoint\else
+ \verticalstrut
+ \nobreak
+ \kern-\struttotal
+ \kern-\parskip
+ \nobreak
+ \nointerlineskip % fix topskip
+ \fi
+ \noindent\strut
+ \hpack to \hsize{\box\tablebox\c_tabl_lines_part\hss}%
+ \endgraf
+ \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax
+ \linetableparameter\c!inbetween
+ \fi}%
+ \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows
+ \linetableparameter\c!inbetween
+ \else
+ % after, later
+ \fi
+ \c_tabl_lines_head_state\plusthree
+ \global\setbox\tablebox\zerocount\emptybox % here
+ \fi
+ % reset \c_tabl_lines_row will be an option, currently
+ % starts at zero after split
+ \global\c_tabl_lines_row\zerocount
+ \global\c_tabl_lines_line\zerocount
+ \global\c_tabl_lines_page\zerocount
+ \global\d_tabl_lines_width\zeropoint
+ \tabl_lines_set
+ \fi}
+
+\def\tabl_lines_start_part
+ {\global\c_tabl_lines_subcol\zerocount
+ \setbox\scratchbox\hbox\bgroup
+ \dousestyleparameter{\linetablerparameter\c!style}%
+ \dousecolorparameter{\linetablerparameter\c!color}%
+ \ignorespaces}
+
+\def\tabl_lines_stop_part
+ {\ifnum\c_tabl_lines_part>\zerocount
+ \unskip \unskip % remove last intercolumn skip (distance+fill)
+ \fi
+ \egroup
+ \ifconditional\c_tabl_lines_preroll \else
+ \ifcase\c_tabl_lines_part
+ % we're collecting the repeater
+ \else
+ \ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch\else
+ \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}%
+ \fi
+ \fi
+ \fi}
+
+\def\tabl_lines_check_part
+ {\global\advance\d_tabl_lines_width\wd\b_tabl_lines_cell
+ \global\advance\c_tabl_lines_column\c_tabl_lines_step
+ \global\advance\c_tabl_lines_subcol\c_tabl_lines_step
+ \relax
+ %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait
+ % from now on the column counter is already incremented
+ \ifcase\c_tabl_lines_split_state
+ \ifconditional\c_tabl_lines_preroll \else
+ \box\b_tabl_lines_cell
+ % the columncounter is one ahead !
+ \hskip\scratchskip
+ \fi
+ %%%
+ \donefalse
+ \ifcase\c_tabl_lines_repeat\else
+ % calculate ahead
+ \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax
+ \donetrue % collecting repeater
+ \fi
+ \fi
+ %%%%
+ \ifdone
+ % collecting repeater
+ \else
+ \ifnum\c_tabl_lines_column>\csname\??linetablepart\number\c_tabl_lines_part\endcsname\relax
+ \donetrue
+ \fi
+ \fi
+ \ifdone
+ \tabl_lines_stop_part
+ \ifconditional\c_tabl_lines_preroll \else
+ \tabl_lines_save_part
+ \fi
+ \ifcase\c_tabl_lines_page \or
+ \global\c_tabl_lines_page \plustwo
+ \else
+ \global\c_tabl_lines_page \plusone
+ \fi
+ \global\advance\c_tabl_lines_part\plusone
+ \global\d_tabl_lines_width\wd\tablebox\zerocount
+ \tabl_lines_start_part
+ \fi
+ \else
+ \donefalse
+ \!!doneafalse
+ \ifcase\c_tabl_lines_repeat\else
+ % calculate ahead
+ \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax
+ \donetrue % collecting repeater
+ \fi
+ \fi
+ \ifdone
+ \!!doneatrue
+ % collecting repeater
+ \orelse\ifdim\d_tabl_lines_width>\hsize
+ \donetrue
+ \else
+ \global\advance\d_tabl_lines_width\scratchskip
+ \ifdim\d_tabl_lines_width>\hsize % ?
+ \donetrue
+ \fi
+ \fi
+ \ifdone
+ \tabl_lines_stop_part
+ \tabl_lines_save_part
+ \ifcase\c_tabl_lines_page \or
+ \global\c_tabl_lines_page \plustwo
+ \else
+ \global\c_tabl_lines_page \plusone
+ \fi
+ \global\advance\c_tabl_lines_part\plusone
+ \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts
+ \global\c_tabl_lines_n_of_parts\c_tabl_lines_part
+ \initializetablebox\c_tabl_lines_part
+ \fi
+ \global\d_tabl_lines_width\wd\b_tabl_lines_cell
+ \tabl_lines_start_part
+ \if!!doneb \else \ifcase\c_tabl_lines_repeat \else
+ % check for left/right page
+ \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi\ifdone
+ % insert repeater
+ \global\advance\d_tabl_lines_width\wd\tablebox\zerocount
+ \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\tablebox\zerocount
+ \fi
+ \fi \fi
+ \fi
+ \ifconditional\c_tabl_lines_preroll \else
+ \box\b_tabl_lines_cell
+ % the columncounter is one ahead !
+ %\dorecurse\c_tabl_lines_step{\strut\hfil}%
+ \strut
+ \hskip\scratchskip
+ \fi
+ \fi}
+
+\permanent\protected\def\startlinetablerun % to do: quit when nested
+ {\bgroup
+ \dontcomplain
+ \settrue\c_tabl_lines_in_table
+ % autowidth
+ \doif{\linetableparameter\c!maxwidth}\v!fit
+ {\setuplinetable[\c!maxwidth=\zeropoint]}%
+ \processaction
+ [\linetableparameter\c!stretch]
+ [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch
+ \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch
+ \c_tabl_lines_repeat\linetableparameter\c!nleft
+ \c_tabl_lines_split_state % =
+ \ifdim\linetableparameter\c!maxwidth>\zeropoint
+ \zerocount \else \plusone
+ \fi
+ % optional prevdepth correction
+ \ifconditional\c_tabl_lines_preroll
+ \global\c_tabl_lines_n_of_rows\zerocount
+ \else
+ \linetableparameter\c!before
+ \fi
+ \global\c_tabl_lines_rows\zerocount
+ \global\c_tabl_lines_n_of_columns\zerocount
+ \global\c_tabl_lines_n_of_parts\zerocount
+ \scratchcounter\zerocount
+ \def\docommand##1%
+ {\global\advance\c_tabl_lines_n_of_parts\plusone
+ \advance\scratchcounter##1%
+ \setxvalue{\??linetablepart\number\c_tabl_lines_n_of_parts}{\the\scratchcounter}}%
+ \processcommacommand[\linetableparameter\c!n]\docommand
+ \initializetableboxes\c_tabl_lines_n_of_parts
+ \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater
+ \global\c_tabl_lines_step\plusone
+ \global\c_tabl_lines_line\zerocount
+ \global\c_tabl_lines_row \zerocount
+ \global\c_tabl_lines_column\zerocount
+ \global\c_tabl_lines_subcol\zerocount
+ \global\d_tabl_lines_width\zeropoint
+ \ifconditional\c_tabl_lines_preroll \else \ifdim\pagetotal>\zeropoint
+ \verticalstrut\kern-\struttotal
+ \fi \fi
+ \tabl_lines_set
+ \tabl_lines_check_page
+ \enforced\let\BR\tabl_lines_BR
+ \enforced\let\ER\tabl_lines_ER
+ \enforced\let\BH\tabl_lines_BR
+ \enforced\let\EH\tabl_lines_ER
+ \enforced\let\BC\tabl_lines_BC
+ \enforced\let\EC\tabl_lines_EC
+ \enforced\let\NC\tabl_lines_NC
+ \enforced\let\NR\tabl_lines_NR
+ \tabl_lines_flush_head}
+
+\permanent\protected\def\stoplinetablerun
+ {\global\c_tabl_lines_line\maxcard
+ \c_tabl_lines_head_state\zerocount % blocked
+ \tabl_lines_flush_parts
+ \ifconditional\c_tabl_lines_preroll \else
+ \linetableparameter\c!after
+ \fi
+ \global\c_tabl_lines_part\zerocount
+ \global\c_tabl_lines_n_of_parts\zerocount
+ \egroup}
+
+\permanent\def\checklinecolumndimension#1#2#3%
+ {\expandafter\xdef\csname#1\number#3\endcsname
+ {\expandafter\ifx\csname#1\number#3\endcsname\relax
+ \the#2\b_tabl_lines_cell
+ \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell
+ \the#2\b_tabl_lines_cell
+ \else
+ \csname#1\number#3\endcsname
+ \fi}}
+
+\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column}
+\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row}
+\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row}
+
+\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented
+ {\ifnum\c_tabl_lines_head_state=1\else
+ \global\advance\c_tabl_lines_row\plusone
+ \global\advance\c_tabl_lines_rows\plusone
+ \fi
+ \global\c_tabl_lines_column\plusone
+ \global\c_tabl_lines_subcol\plusone
+ \d_tabl_lines_height\zeropoint
+ \edef\p_height{\linetablerparameter\c!height}%
+ \ifx\p_height\empty
+ \c_tabl_lines_hmode \zerocount
+ \orelse\ifx\p_height\v!fit
+ \c_tabl_lines_hmode \plusone
+ \orelse\ifx\p_height\v!line
+ \c_tabl_lines_hmode \plustwo
+ \else
+ \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax
+ \fi
+ \tabl_lines_start_part}
+
+\permanent\protected\def\tabl_lines_BC
+ {\startlinetablecell}
+
+\permanent\protected\def\tabl_lines_EC
+ {\stoplinetablecell
+ \ifconditional\c_tabl_lines_preroll
+ \tabl_lines_check_width
+ \tabl_lines_check_height
+ \tabl_lines_check_depth
+ \fi
+ \tabl_lines_check_part}
+
+\permanent\protected\def\tabl_lines_ER
+ {% \stoplinetablecell
+ % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR
+ \tabl_lines_stop_part
+ \tabl_lines_save_part
+ \advance\c_tabl_lines_column \minusone
+ \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns
+ \global\c_tabl_lines_n_of_columns\c_tabl_lines_column
+ \fi
+ \tabl_lines_flush_parts
+ \global\c_tabl_lines_column\zerocount
+ \global\d_tabl_lines_width \zeropoint
+ \ifcase\c_tabl_lines_repeat
+ \global\c_tabl_lines_part\plusone
+ \else
+ \global\c_tabl_lines_part\zerocount % repeater
+ \fi
+ \tabl_lines_check_page
+ \tabl_lines_flush_head}
+
+\def\tabl_lines_check_page
+ {\global\c_tabl_lines_page\zerocount
+ \ifcase\c_tabl_lines_repeat \else \ifcase\c_tabl_lines_page
+ \doif{\linetableparameter\c!repeat}\v!no
+ {\global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo}%
+ \fi \fi}
+
+\def\tabl_lines_flush_head
+ {\ifcase\c_tabl_lines_head_state
+ % 0 blocked
+ \or
+ % 1 doing head
+ \or
+ % 2 head done
+ \or
+ % 3 trigger flush
+ \c_tabl_lines_head_state\plusone
+ \the\t_tabl_lines_head\relax
+ \c_tabl_lines_head_state\plustwo
+ \fi}
+
+\permanent\protected\def\tabl_lines_NC % first time special treatment
+ {\relax
+ \ifcase\c_tabl_lines_column
+ \tabl_lines_BR
+ \else
+ \tabl_lines_EC
+ \fi
+ \tabl_lines_BC} % beware, this will result in BR BC EC BC NR
+
+\permanent\protected\def\tabl_lines_NR
+ {\stoplinetablecell % dummy
+ \tabl_lines_ER}
+
+\permanent\protected\def\startlinetable
+ {\startlinetablerun}
+
+\permanent\protected\def\stoplinetable
+ {\stoplinetablerun}
+
+\permanent\protected\def\startlinetableanalysis
+ {\bgroup
+ \settrue\c_tabl_lines_preroll
+ \settrialtypesetting
+ \startlinetablerun}
+
+% \protected\def\stoplinetableanalysis
+% {\stoplinetablerun
+% \egroup
+% \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
+% \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
+% {\setevalue{\??linetable r:\recurselevel x\c!height}{\getvalue{\??linetableheight\recurselevel}}%
+% \setevalue{\??linetable r:\recurselevel x\c!depth }{\getvalue{\??linetabledepth \recurselevel}}%
+% \letgvalue{\??linetableheight\recurselevel}\!!zeropoint
+% \letgvalue{\??linetabledepth \recurselevel}\!!zeropoint}
+% \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
+% {\setevalue{\??linetable c:\recurselevel\c!width}{\getvalue{\??linetablewidth\recurselevel}}%
+% \letgvalue{\??linetablewidth\recurselevel}\!!zeropoint}} % init next table
+
+\permanent\protected\def\stoplinetableanalysis
+ {\stoplinetablerun
+ \egroup
+ \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
+ \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
+ {\setevalue{\??linetable r:##1x\c!height}{\csname\??linetableheight##1\endcsname}%
+ \setevalue{\??linetable r:##1x\c!depth }{\csname\??linetabledepth ##1\endcsname}%
+ \letgvalue{\??linetableheight##1}\zeropoint
+ \letgvalue{\??linetabledepth ##1}\zeropoint}
+ \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
+ {\setevalue{\??linetable c:##1\c!width}{\csname\??linetablewidth##1\endcsname}%
+ \letgvalue{\??linetablewidth##1}\zeropoint}} % init next table
+
+% todo: store in box instead of macro
+
+\aliased\let\stoplinetablehead\relax
+
+\permanent\protected\def\startlinetablehead#1\stoplinetablehead
+ {\ifconditional\c_tabl_lines_in_table
+ \t_tabl_lines_head\emptytoks
+ \fi
+ \c_tabl_lines_head_state\plusthree % full
+ \t_tabl_lines_head{#1}%
+ \ifconditional\c_tabl_lines_in_table
+ \tabl_lines_flush_head
+ \fi}
+
+\permanent\protected\def\tabl_lines_BH
+ {\ifx\EC\relax
+ % signal, grabbing lines
+ \else
+ \t_tabl_lines_head\emptytoks
+ \fi
+ \push_macro_BC
+ \push_macro_EC
+ \enforced\permanent\protected\def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}%
+ \enforced\permanent \let\EC\relax} % signal
+
+\permanent\protected\def\tabl_lines_EH
+ {\pop_macro_EC
+ \pop_macro_BC
+ \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead}
+
+\permanent\let\startlinetablebody\relax
+\permanent\let\stoplinetablebody \relax
+
+\protected\def\processlinetablebuffer
+ {\dosingleempty\tabl_lines_process_buffer}
+
+\def\tabl_lines_process_buffer[#1]%
+ {\bgroup
+ \enforced\let\startlinetable\relax
+ \enforced\let\stoplinetable \relax
+ \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis
+ \startlinetablerun \getbuffer[#1]\stoplinetablerun
+ \egroup}
+
+\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1]
+ {\bgroup
+ \enforced\let\startlinetable\relax
+ \enforced\let\stoplinetable \relax
+ \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis
+ \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun
+ \egroup}
+
+\popoverloadmode
+
+\setuplinetable
+ [\c!n=\maxcard,
+ \c!lines=\maxcard,
+ \c!nx=\plusone,
+ \c!nleft=\zerocount,
+ \c!repeat=\v!yes, % when nleft > 0, repeat on both pages
+ \c!before=,
+ \c!after=,
+ \c!inbetween=\page,
+ \c!distance=\zeropoint,
+ \c!stretch=\v!no,
+ \c!align=\c!right,
+ \c!leftoffset=.25\exheight,
+ \c!rightoffset=\linetableparameter\c!leftoffset,
+ \c!maxwidth=\zeropoint,
+ \c!width=5\emwidth,
+ \c!height=\v!fit, % \v!line = faster
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!rulethickness=\linewidth]
+
+\protect
+
+\continueifinputfile{tabl-ltb.mkxl}
+
+\setuplinetable[n=6,m={2,2,2},lines=25] % m ?
+
+\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red]
+\setuplinetable[c][4] [width=3cm,background=color,backgroundcolor=yellow]
+\setuplinetable[c][6] [width=3cm,background=color,backgroundcolor=magenta]
+\setuplinetable[r][odd] [background=color,backgroundcolor=gray]
+\setuplinetable[r][even][background=color,backgroundcolor=green]
+
+\starttext
+
+\showframe \showstruts
+
+\setuppagenumbering[alternative=doublesided]\page[left]
+
+\startlinetable
+\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR
+\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
+\stoplinetable
+
+\startlinetable
+\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx
+ \NC yy \NC ddddd \NC eeee \NC ff \NC \NR
+\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
+\stoplinetable
+
+% \startbuffer[lt]
+% \NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC ee \NC ff \NC \NR
+% \NC aaa\crlf aaa \NC b \NC cc \NC ddd \NC eeee \NC f \NC \NR
+% \stopbuffer
+%
+% \processlinetablebuffer[lt]
+
+\stoptext
diff --git a/tex/context/base/mkiv/tabl-mis.mkiv b/tex/context/base/mkiv/tabl-mis.mkiv
index b2af1993e..d9022b06d 100644
--- a/tex/context/base/mkiv/tabl-mis.mkiv
+++ b/tex/context/base/mkiv/tabl-mis.mkiv
@@ -130,7 +130,7 @@
\let\typo_paragraphs_setup_saved\setupparagraphs
-\unexpanded\def\setupparagraphs
+\unexpanded\overloaded\def\setupparagraphs
{\dotripleempty\typo_paragraphs_setup}
\def\typo_paragraphs_setup[#1][#2][#3]% we are downward compatible with [each] and [1,3]
@@ -193,7 +193,7 @@
\fi
\parindent\zeropoint
\c_typo_paragraphs_n\zerocount
- \let\\=\typo_paragraphs_next % downward compatible
+ \enforced\let\\\typo_paragraphs_next % downward compatible
\edef\p_offset{\paragraphsparameter\c!offset}%
\doifelsedimension\p_offset
{\scratchoffset\p_offset}%
diff --git a/tex/context/base/mkiv/tabl-ntb.mkxl b/tex/context/base/mkiv/tabl-ntb.mkxl
index 680429822..300821107 100644
--- a/tex/context/base/mkiv/tabl-ntb.mkxl
+++ b/tex/context/base/mkiv/tabl-ntb.mkxl
@@ -44,12 +44,12 @@
% \eTR
% \eTABLE
-% \unexpanded\def\startrow {\bTR}
-% \unexpanded\def\stoprow {\eTR}
-% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD}
-% \let\stopcell \relax
-% \let\startcelltable \bTABLE
-% \let\stopcelltable \eTABLE
+% \protected\def\startrow {\bTR}
+% \protected\def\stoprow {\eTR}
+% \protected\def\startcell#1\stopcell{\bTD#1\eTD}
+% \let\stopcell \relax
+% \let\startcelltable \bTABLE
+% \let\stopcelltable \eTABLE
% \starttext
% \startcelltable
@@ -100,7 +100,7 @@
% maybe: \the\neverypar
\to \t_tabl_ntb_cell_start
-\unexpanded\def\tabl_ntb_cell_start
+\protected\def\tabl_ntb_cell_start
{% \inhibitblank
\dotagTABLEcell
%\tabl_ntb_next_level
@@ -109,7 +109,7 @@
\everypar\t_tabl_ntb_cell_start
\font_styles_math_start}
-\unexpanded\def\tabl_ntb_cell_stop
+\protected\def\tabl_ntb_cell_stop
{\font_styles_math_stop
\ifhmode
\the\t_tabl_ntb_cell_stop
@@ -123,7 +123,7 @@
% maybe:
%
-% \unexpanded\def\tabl_ntb_cell_stop
+% \protected\def\tabl_ntb_cell_stop
% {\ifhmode
% \the\t_tabl_ntb_cell_stop
% \par % added 13/4/2006
@@ -213,7 +213,7 @@
\installglobalmacrostack\m_tabl_ntb_saved_row
\installglobalmacrostack\m_tabl_ntb_saved_col
-\unexpanded\def\tabl_ntb_table_push
+\protected\def\tabl_ntb_table_push
{\ifnum\m_tabl_tbl_level>\plusone
\tabl_ntb_parameters_reset
% we need a proper count push/pop
@@ -223,7 +223,7 @@
\global\intabletrue
\fi}
-\unexpanded\def\tabl_ntb_table_pop
+\protected\def\tabl_ntb_table_pop
{\ifnum\m_tabl_tbl_level>\plusone
\pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row
\pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col
@@ -231,11 +231,11 @@
\global\intablefalse
\fi}
-\unexpanded\def\tabl_ntb_next_level
+\protected\def\tabl_ntb_next_level
{\advance\c_tabl_level\plusone
\edef\m_tabl_tbl_level{\the\c_tabl_level}}
-\unexpanded\def\tabl_ntb_prev_level
+\protected\def\tabl_ntb_prev_level
{\advance\c_tabl_level\minusone
\edef\m_tabl_tbl_level{\the\c_tabl_level}}
@@ -247,8 +247,8 @@
\installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable
\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal
-\unexpanded\def\bTABLEnested{\tabl_ntb_next_level\bTABLE}
-\unexpanded\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level}
+\permanent\protected\def\bTABLEnested{\tabl_ntb_next_level\bTABLE}
+\permanent\protected\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level}
\installcorenamespace{naturaltabletal}
\installcorenamespace{naturaltablegal}
@@ -353,18 +353,6 @@
% \c_tabl_ntb_none
% \fi}
-% not used
-%
-% \def\tabl_ntb_tag_state#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
-% \def\tabl_ntb_row_state#1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
-% \def\tabl_ntb_col_state#1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
-
-%def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
-%def\tabl_ntb_spn_doifelse#1{\doifelse {\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname}\!!plusone}
-
-%def\tabl_ntb_set_spn #1{\setvalue {\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
-%def\tabl_ntb_spn_doifelse#1{\doifelsevalue{\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
-
\def\tabl_ntb_let_ref #1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_set_ref #1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
%def\tabl_ntb_get_ref #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
@@ -379,11 +367,11 @@
% keep for a while:
%
-% \unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level
+% \protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level
% {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\expandafter\endcsname\expandafter
% {\expandafter\def\expandafter\m_tabl_tbl_level\expandafter{\m_tabl_tbl_level}\tabl_ntb_cell_process{#3}{#4}[#5]{#6}}}
-\unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
+\protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
{\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname
{\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_ntb_next_level#6\tabl_ntb_prev_level}}}
@@ -414,25 +402,24 @@
% so far
-\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{}
-
-\unexpanded\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax
-\unexpanded\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax
-\unexpanded\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax
+\protected\def\tabl_ntb_cell_process#1#2[#3]{}
-\unexpanded\def\setupTABLE
- {\dotripleempty\tabl_ntb_setup}
+\permanent\protected\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax
+\permanent\protected\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax
+\permanent\protected\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax
\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
-\def\tabl_ntb_setup
- {\ifthirdargument
+\permanent\tolerant\protected\def\setupTABLE[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ \expandafter\gobblethreeoptionals
+ \or
+ \expandafter\tabl_ntb_setup_one
+ \or
+ \expandafter\tabl_ntb_setup_two
+ \or
\expandafter\tabl_ntb_setup_three
- \orelse\ifsecondargument
- \doubleexpandafter\tabl_ntb_setup_two
- \else
- \doubleexpandafter\tabl_ntb_setup_one
- \fi}
+ \fi[#1][#2][#3]}
\def\tabl_ntb_setup_one[#1][#2][#3]%
{\setupcurrentnaturaltablelocal[#1]}
@@ -457,9 +444,6 @@
\installcorenamespace{naturaltablesetupthree}
\installcorenamespace{naturaltablesetuptwo}
-%def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
-%def\tabl_ntb_setup_two [#1]{\csname\??naturaltablesetuptwo \ifcsname\??naturaltablesetuptwo #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
-
\def\tabl_ntb_setup_three[#1]{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi[#1]}
\def\tabl_ntb_setup_two [#1]{\ifcsname\??naturaltablesetuptwo #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi[#1]}
@@ -492,7 +476,7 @@
\def\tabl_ntb_parameters_get[##1]%
{\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}%
\csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
- \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+ \enforced\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
\else
\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
\fi
@@ -562,7 +546,7 @@
\let\tabl_ntb_setup_section\relax
-\unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
+\protected\def\tabl_ntb_setup_cell#1#2% cell over col over row
{\tabl_ntb_setup_section % already forgotten
\edef\m_tabl_ntb_positive_row{\number#1}%
\edef\m_tabl_ntb_positive_col{\number#2}%
@@ -671,7 +655,7 @@
% \bTR \bTD left \eTD\bTD right \eTD\eTR
% \eTABLE
-\unexpanded\def\tabl_ntb_tr
+\protected\def\tabl_ntb_tr
{\c_tabl_ntb_running_col\zerocount
\c_tabl_ntb_encountered_col\zerocount
\advance\c_tabl_ntb_maximum_row\plusone
@@ -687,7 +671,7 @@
\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr}
\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc}
-\unexpanded\def\tabl_ntb_td
+\protected\def\tabl_ntb_td
{\advance\c_tabl_ntb_encountered_col\plusone
\iffirstargument
\expandafter\tabl_ntb_td_yes
@@ -912,18 +896,18 @@
% to be done: head <raw> foot, dus state var
-\unexpanded\def\bTABLEhead{\dosingleempty\tabl_ntb_head} \let\eTABLEhead\relax
-\unexpanded\def\bTABLEnext{\dosingleempty\tabl_ntb_next} \let\eTABLEnext\relax
-\unexpanded\def\bTABLEbody{\dosingleempty\tabl_ntb_body} \let\eTABLEbody\relax
-\unexpanded\def\bTABLEfoot{\dosingleempty\tabl_ntb_foot} \let\eTABLEfoot\relax
+\let\eTABLEhead\relax
+\let\eTABLEnext\relax
+\let\eTABLEbody\relax
+\let\eTABLEfoot\relax
-\def\tabl_ntb_head[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
-\def\tabl_ntb_next[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
-\def\tabl_ntb_body[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
-\def\tabl_ntb_foot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
+\permanent\tolerant\protected\def\bTABLEhead[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\permanent\tolerant\protected\def\bTABLEnext[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\permanent\tolerant\protected\def\bTABLEbody[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\permanent\tolerant\protected\def\bTABLEfoot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
\def\tabl_ntb_section[#1]#2% also used in tabl-nte
- {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
+ {\protected\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
#2%
\let\tabl_ntb_setup_section\relax}
@@ -932,10 +916,7 @@
\begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
\begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname}
-\unexpanded\def\bTABLE
- {\dosingleempty\tabl_ntb_table}
-
-\def\tabl_ntb_table[#1]%
+\permanent\tolerant\protected\def\bTABLE[#1]%
{\tabl_ntb_table_push
% box not here
\bgroup
@@ -984,10 +965,10 @@
\let\currentTABLEcolumn\tabl_ntb_current_column
\let\nofTABLErows \tabl_ntb_n_of_rows
\let\nofTABLEcolumns \tabl_ntb_n_of_columns
- \let\bTR\dobTR
- \let\bTD\dobTD
- \let\bTH\dobTH
- \let\bTN\dobTN}
+ \enforced\let\bTR\dobTR
+ \enforced\let\bTD\dobTD
+ \enforced\let\bTH\dobTH
+ \enforced\let\bTN\dobTN}
\def\tabl_ntb_current_row {\m_tabl_ntb_positive_row}
\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col}
@@ -1001,19 +982,21 @@
% there is no gain in a \doifelsenextoptionalcs variant
-\unexpanded\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte
-\unexpanded\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte
-\unexpanded\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte
-\unexpanded\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte
+% todo with tolerant:
+
+\permanent\protected\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte
+\permanent\protected\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte
+\permanent\protected\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte
+\permanent\protected\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte
% permits \expanded{\bTD ... \eTD}
-\let\bTR\relax \unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows
-\let\bTD\relax \unexpanded\def\eTD{\ignorespaces}
-\let\bTH\relax \unexpanded\def\eTH{\ignorespaces}
-\let\bTN\relax \unexpanded\def\eTN{\ignorespaces}
+\permanent\let\bTR\relax \permanent\protected\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows
+\permanent\let\bTD\relax \permanent\protected\def\eTD{\ignorespaces}
+\permanent\let\bTH\relax \permanent\protected\def\eTH{\ignorespaces}
+\permanent\let\bTN\relax \permanent\protected\def\eTN{\ignorespaces}
-\unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
+\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
{% tricky and dirty order -)
\setfalse\c_tabl_ntb_okay
% head
@@ -1214,12 +1197,12 @@
\the\t_tabl_ntb_row
\tabl_ntb_row_align_stop}}
-\unexpanded\def\tabl_ntb_row_align_set#1#2#3%
+\protected\def\tabl_ntb_row_align_set#1#2#3%
{\xdef\m_tabl_ntb_before_split{#1}%
\xdef\m_tabl_ntb_after_split {#2}%
\xdef\m_tabl_ntb_same_page {#3}}
-\unexpanded\def\tabl_ntb_row_align_reset
+\protected\def\tabl_ntb_row_align_reset
{\glet\m_tabl_ntb_before_split\empty
\glet\m_tabl_ntb_after_split \empty
\glet\m_tabl_ntb_same_page \empty}
@@ -1229,7 +1212,7 @@
% \prelocateTBLrows{1000} % may speed up large tables
-\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
+\permanent\protected\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
{\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone
{\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}%
\def\tabl_ntb_row_start
@@ -1296,7 +1279,7 @@
\fi
\fi}
-\unexpanded\def\tabl_ntb_row_align_start
+\protected\def\tabl_ntb_row_align_start
{\global\advance\c_tabl_ntb_row\plusone
\global\c_tabl_ntb_col\plusone
\global\c_tabl_ntb_spn\zerocount
@@ -1307,7 +1290,7 @@
\hbox\bgroup
\kern\dimexpr\d_tabl_ntb_leftmargindistance\relax}
-\unexpanded\def\tabl_ntb_row_align_stop
+\protected\def\tabl_ntb_row_align_stop
{\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax
\egroup
\ifconditional\c_strc_tags_enabled
@@ -1315,7 +1298,7 @@
\fi
\tabl_ntb_row_align_stop_inject}
-\unexpanded\def\tabl_ntb_before_page
+\protected\def\tabl_ntb_before_page
{\ifx\m_tabl_ntb_same_page\v!before
% \blank[\v!samepage,\v!strong]%
\unpenalty
@@ -1326,7 +1309,7 @@
\nobreak
\fi}
-\unexpanded\def\tabl_ntb_after_page
+\protected\def\tabl_ntb_after_page
{\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines
\ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount
\unpenalty
@@ -1346,7 +1329,7 @@
\allowbreak % else no proper head split off
\fi}
-\unexpanded\def\tabl_ntb_inbetween
+\protected\def\tabl_ntb_inbetween
{\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
\ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax
\ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax
@@ -1357,7 +1340,7 @@
\fi
\fi}
-\unexpanded\def\tabl_ntb_row_align_start_inject
+\protected\def\tabl_ntb_row_align_start_inject
{\bgroup % protect local vars
\m_tabl_ntb_before_split
\egroup
@@ -1365,7 +1348,7 @@
\tabl_ntb_before_page
\fi}
-\unexpanded\def\tabl_ntb_row_align_stop_inject
+\protected\def\tabl_ntb_row_align_stop_inject
{\par
\nointerlineskip
\ifenableTBLbreak
@@ -1389,16 +1372,16 @@
\the\t_tabl_ntb
\dostoptagged}
-\unexpanded\def\tabl_ntb_span#1%
+\protected\def\tabl_ntb_span#1%
{\hskip\tabl_ntb_get_dis\c_tabl_ntb_col
\dorecurse{#1}
{\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax
\global\advance\c_tabl_ntb_col\plusone}}
-\unexpanded\def\tabl_ntb_skip#1%
+\protected\def\tabl_ntb_skip#1%
{\global\advance\c_tabl_ntb_col#1\relax}
-\unexpanded\def\tabl_ntb_plus
+\protected\def\tabl_ntb_plus
{\global\advance\c_tabl_ntb_col\plusone
\kern\d_tabl_ntb_columndistance}
@@ -1421,10 +1404,10 @@
\fi}%
\fi}
-\unexpanded\def\tabl_ntb_cell#1#2%
+\protected\def\tabl_ntb_cell#1#2%
{\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}}
-\unexpanded\def\tabl_ntb_table_start
+\protected\def\tabl_ntb_table_start
{\global\c_tabl_ntb_spn\zerocount
\global\c_tabl_ntb_row\zerocount
\global\c_tabl_ntb_col\zerocount
@@ -1522,13 +1505,6 @@
\fi
\dostoptagged} % right spot
-% \def\tabl_ntb_cell_finalize
-% {\doifnotinset\localwidth{\v!fit,\v!broad}% user set
-% {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
-% \ifdim\localwidth>\scratchdimen
-% \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
-% \fi}}
-
\def\tabl_ntb_cell_finalize
{\ifx\localwidth\v!fit
% nothing
@@ -1643,11 +1619,11 @@
\c_tabl_tbl_pass\plusthree
\let\tabl_ntb_pass\tabl_ntb_pass_three
\ifnum\m_tabl_tbl_level>\plusone
- \tabl_tbl_split_nop
+ \tabl_ntb_split_nop
\orelse\ifenableTBLbreak
- \tabl_tbl_split_yes
+ \tabl_ntb_split_yes
\else
- \tabl_tbl_split_nop
+ \tabl_ntb_split_nop
\fi}
\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend
@@ -1677,7 +1653,7 @@
\fi
\fi}
-\def\tabl_tbl_split_nop
+\def\tabl_ntb_split_nop
{\setbox\b_tabl_ntb_final\vbox{\tabl_ntb_flush_content}%
\postprocessTABLEbox\b_tabl_ntb_final
\beforeTABLEbox
@@ -1693,7 +1669,7 @@
\box\b_tabl_ntb_final
\afterTABLEbox}
-\def\tabl_tbl_split_yes
+\def\tabl_ntb_split_yes
{\ifinsidesplitfloat
\donetrue
\orelse\ifinsidefloat
@@ -1704,7 +1680,7 @@
\ifdone
\expandafter\tabl_ntb_split_box
\else
- \expandafter\tabl_tbl_split_nop
+ \expandafter\tabl_ntb_split_nop
\fi}
\newbox\TABLEsplitbox % public, don't change
@@ -1897,14 +1873,14 @@
\typo_charalign_adapt_font
\signalcharacteralign{#2}{#1}}
-\unexpanded\def\tabl_ntb_cell_process_a_extra#1#2%
+\protected\def\tabl_ntb_cell_process_a_extra#1#2%
{\ifcase\tabl_ntb_get_tal{#2}\relax
\expandafter\tabl_ntb_cell_process_x
\else
\expandafter\tabl_ntb_cell_process_a
\fi{#1}{#2}}
-\unexpanded\def\tabl_ntb_cell_process_x#1#2[#3]#4%
+\protected\def\tabl_ntb_cell_process_x#1#2[#3]#4%
{}
% problem: when span doesn't break we can have a span that is the sum of cells but
@@ -1933,7 +1909,7 @@
\tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
\fi}
-\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
+\protected\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
{\bgroup
\letnaturaltablelocalparameter\c!option\empty
\tabl_ntb_setup_cell{#1}{#2}%
@@ -1993,7 +1969,7 @@
\box\scratchboxone
\egroup}
-\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5%
+\protected\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5%
{\setbox\scratchbox\hbox
{\tabl_ntb_setup_cell{#2}{#3}%
\setupcurrentnaturaltablelocal[#4,#1]%
@@ -2017,7 +1993,7 @@
\fi
\box2 }
-\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4%
+\protected\def\tabl_ntb_cell_process_b#1#2[#3]#4%
{\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
\ifdim\scratchdimen>\zeropoint\relax
\else
@@ -2031,10 +2007,10 @@
\normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
{#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}}
-\unexpanded\def\tabl_ntb_cell_process_c
+\protected\def\tabl_ntb_cell_process_c
{\tabl_ntb_cell_process_b_c{}}
-\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4%
+\protected\def\tabl_ntb_cell_process_d#1#2[#3]#4%
{\tabl_ntb_setup_cell{#1}{#2}%
\bgroup
\setupcurrentnaturaltablelocal[#3]%
@@ -2044,7 +2020,7 @@
\inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
\egroup}
-\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4%
+\protected\def\tabl_ntb_cell_process_e#1#2[#3]#4%
{\tabl_ntb_setup_cell{#1}{#2}%
\setupcurrentnaturaltablelocal[#3]% to get the color right, the way we
\color % handle color here prevents interference due to whatsit nodes
@@ -2185,19 +2161,16 @@
\installcorenamespace{naturaltablesetup}
-\unexpanded\def\defineTABLEsetup
- {\dodoubleargument\tabl_ntb_define_setup}
-
-\def\tabl_ntb_define_setup[#1][#2]%
- {\setvalue{\??naturaltablesetup#1}{#2}}
+\permanent\tolerant\protected\def\defineTABLEsetup[#1]#*[#2]%
+ {\ifarguments\else\setvalue{\??naturaltablesetup#1}{#2}\fi}
-\let\eTDs\relax
-\let\eTRs\relax
+\permanent\let\eTDs\relax
+\permanent\let\eTRs\relax
-\unexpanded\def\bTDs[#1]#2\eTDs
+\permanent\protected\def\bTDs[#1]#2\eTDs
{\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}
-\unexpanded\def\bTRs[#1]#2\eTRs
+\permanent\protected\def\bTRs[#1]#2\eTRs
{\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}
\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-nte.mkiv b/tex/context/base/mkiv/tabl-nte.mkiv
index af74a2abe..2a8c4c7dd 100644
--- a/tex/context/base/mkiv/tabl-nte.mkiv
+++ b/tex/context/base/mkiv/tabl-nte.mkiv
@@ -81,10 +81,10 @@
\setfalse\c_tabl_nte_in_nc}
\unexpanded\def\tabl_nte_start_nc
- {\futurelet\next\tabl_nte_start_nc_indeed}
+ {\futurelet\nexttoken\tabl_nte_start_nc_indeed}
\def\tabl_nte_start_nc_indeed
- {\ifx\next\tabl_nte_start_nr \else
+ {\ifx\nexttoken\tabl_nte_start_nr \else
\expandafter\tabl_nte_start_nc_finish
\fi}
diff --git a/tex/context/base/mkiv/tabl-nte.mkxl b/tex/context/base/mkiv/tabl-nte.mkxl
new file mode 100644
index 000000000..40213ad90
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-nte.mkxl
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=core-nte,
+%D version=2009.03.08,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural Tables Extensions,
+%D author=Hans Hagen \& Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Module / Natural Tables Extensions}
+
+\unprotect
+
+%D This module is suggested by Wolfgang Schuster who also prototyped
+%D it and came up with the rationale:
+%D
+%D This module provides an easy way to use natural in a similiar
+%D way as the older table module (based on the \TABLE\ macros) and
+%D the newer tabulate module.
+%D
+%D You can see the advantage in the following table, once created
+%D with the new macros and once with the normal macros provided
+%D with the natural table module.
+%D
+%D Let us start with the original macros:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR
+%D \bTD Text 1 \eTD
+%D \bTD Text 2 \eTD
+%D \eTR
+%D \bTR
+%D \bTD Text 3 \eTD
+%D \bTD Text 4 \eTD
+%D \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Watch how the new macros use less code:
+%D
+%D \startbuffer
+%D \startTABLE
+%D \NC Text 1 \NC Text 2 \NC\NR
+%D \NC Text 3 \NC Text 4 \NC\NR
+%D \stopTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The actual code differs from the prototype that it does not need
+%D to collect whole rows and parse them but looks ahead instead.
+
+\newconditional\c_tabl_nte_in_nc
+
+\permanent\tolerant\protected\def\startTABLE[#1]%
+ {\bgroup
+ \bTABLE[#1]%
+ \enforced\let\NC\tabl_nte_start_nc
+ \enforced\let\NR\tabl_nte_start_nr
+ \enforced\let\bTR\relax
+ \enforced\let\bTD\relax
+ \enforced\let\bTH\relax
+ \enforced\let\bTN\relax}
+
+\permanent\protected\def\stopTABLE
+ {\eTABLE
+ \egroup}
+
+\permanent\protected\def\tabl_nte_start_nr
+ {\eTR
+ \setfalse\c_tabl_nte_in_nc}
+
+\permanent\protected\def\tabl_nte_start_nc
+ {\futurelet\nexttoken\tabl_nte_start_nc_indeed}
+
+\def\tabl_nte_start_nc_indeed
+ {\ifx\nexttoken\tabl_nte_start_nr \else
+ \expandafter\tabl_nte_start_nc_finish
+ \fi}
+
+\def\tabl_nte_start_nc_finish#1\NC
+ {\ifconditional\c_tabl_nte_in_nc \else
+ \settrue\c_tabl_nte_in_nc
+ \dobTR[]%
+ \fi
+ \dobTD#1\eTD\NC}
+
+%D The related structure commands are also available:
+
+\permanent\let\stopTABLEhead\relax
+\permanent\let\stopTABLEnext\relax
+\permanent\let\stopTABLEbody\relax
+\permanent\let\stopTABLEfoot\relax
+
+\permanent\tolerant\protected\def\startTABLEhead[#1]#:#2\stopTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\permanent\tolerant\protected\def\startTABLEnext[#1]#:#2\stopTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\permanent\tolerant\protected\def\startTABLEbody[#1]#:#2\stopTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\permanent\tolerant\protected\def\startTABLEfoot[#1]#:#2\stopTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-tab.mkiv b/tex/context/base/mkiv/tabl-tab.mkiv
index 3799964c9..e646a1a18 100644
--- a/tex/context/base/mkiv/tabl-tab.mkiv
+++ b/tex/context/base/mkiv/tabl-tab.mkiv
@@ -1739,7 +1739,7 @@
%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\
%D handles alignments, we cannot automate spacing for colored rows and columns.
-\setnewconstant\tablerowzero\zerocount
+\tablerowzero\zerocount
\appendtoks
\let\SR\tabl_table_SR
diff --git a/tex/context/base/mkiv/tabl-tab.mkxl b/tex/context/base/mkiv/tabl-tab.mkxl
new file mode 100644
index 000000000..5fb7f928c
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-tab.mkxl
@@ -0,0 +1,2229 @@
+%D \module
+%D [ file=core-tab,
+%D version=1997.10.10,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=\TABLE\ Embedding,
+%D author=Hans Hagen with copied and patched code from MJ Wichura,
+%D date=\currentdate]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / TaBlE Embedding}
+
+% Todo: just for the fun of it ... use lmtx features.
+
+% Todo: a bitmore namespace protection ... although we want to keep some of the
+% original flavour.
+%
+% In \MKIV\ the old table macros are sort of obsolete. The color extensions have
+% been removed and some code is stripped. For practical reasons the \TABLE\ macros
+% that are used are embedded in this file.
+%
+% The following code is based on TABLE 1.0 by Michael J. Wichura (August 1988. We
+% used a patched version with many overloads and extensions. The documented (and
+% larger) source can be found in \type {thrd-tab.tex}.
+%
+% Some code has been stripped. Some color has been added. Some macros have been
+% renamed. Registers have been replaces. And probably much more can be cleaned up.
+% We also need to use \tabl_tab_ prefixes here.
+
+\unprotect
+
+\newconditional\c_tabl_table_spacing_left
+\newconditional\c_tabl_table_spacing_right
+
+\newdimen \d_tabl_table_line_thickness_unit
+\newdimen \d_tabl_table_strut_unit
+\newskip \s_tabl_table_inter_column_space_unit
+\newdimen \d_tabl_table_column_width_unit
+\newdimen \d_tabl_table_kern_unit
+
+\def\tablestrutheightfactor {8}
+\def\tablestrutdepthfactor {3}
+\def\tableintercolumnspacefactor {3}
+\def\tablecolumnwidthfactor {10}
+\def\tablevspacefactor {2}
+\def\tablekernfactor {1}
+\def\tablelinethicknessfactor {4}
+
+\newtoks\everytable
+\newtoks\everytableparbox
+
+\protected\def\tabl_table_begin_par_box#1%
+ {\setbox\scratchbox\vtop\bgroup % \setbox added
+ \hsize#1\relax
+ \dontcomplain
+ \tabl_table_restore_lineskips
+ \normalbaselines
+ \enforced\let~\fixedspace
+ \inhibitblank % \blank[\v!disable]% % added
+ \the\everytableparbox}
+
+\protected\def\tabl_table_end_par_box
+ {\removelastskip % itemize or so
+ \endgraf
+ \ifnum\prevgraf>\zerocount % we want at least
+ \verticalstrut \nowhitespace \vskip-\struttotal % one line of text
+ \egroup
+ \ifdim\dp\scratchbox>\lineheight % see (*) for an
+ \getnoflines{\dp\scratchbox}% % example of where
+ \dp\scratchbox\zeropoint % saving can go
+ \setbox\scratchbox % terrible wrong
+ \vtop to \noflines\lineheight{\box\scratchbox}%
+ \fi % esp between rows
+ \else % of paragraphs
+ \egroup
+ \fi
+ \box\scratchbox}
+
+\appendtoks
+ \parindent\zeropoint
+ \raggedright
+ \rightskip\zeropoint \s!plus 4em \relax
+\to \everytableparbox
+
+\newskip \tablelefttabskip
+\newskip \tablerighttabskip
+
+\newcount\!taColumnNumber
+\newcount\!taRecursionLevel % (Initially 0)
+
+\newdimen\!taDimenA % used by \Enlarge
+\newdimen\!taDimenB % used by \Enlarge
+\newdimen\!taDimenC % used by numeric.tex
+\newdimen\!taMinimumColumnWidth
+
+\newtoks \!taTableSpread
+\newtoks \!taPreamble
+\newtoks \!taDataColumnTemplate
+\newtoks \!taRuleColumnTemplate
+\newtoks \!taOldRuleColumnTemplate
+\newtoks \!taLeftGlue
+\newtoks \!taRightGlue
+
+\newskip \!taLastRegularTabskip
+
+\newif \if!taBeginFormat
+\newif \if!taOnceOnlyTabskip
+
+\def\!thToksEdef#1#2%
+ {\edef\tempstring{#2}%
+ #1\expandafter{\tempstring}%
+ \ignorespaces}
+
+\def\!thLoop#1\repeat
+ {\def\!thIterate{#1\expandafter\!thIterate\fi}%
+ \!thIterate
+ \let\!thIterate\relax}
+
+\def\tabl_table_begin_format
+ {\!taPreamble\emptytoks
+ \!taColumnNumber\zerocount
+ \scratchskip\s_tabl_table_inter_column_space_unit
+ \multiply\scratchskip\tableintercolumnspacefactor
+ \divide\scratchskip\plustwo
+ \!taRuleColumnTemplate\expandafter{\expandafter\tabskip\the\scratchskip}%
+ \!taLastRegularTabskip\scratchskip
+ \!taOnceOnlyTabskipfalse
+ \!taBeginFormattrue
+ \let\!tfRowOfWidths\empty
+ \doreadtableformatkeys}
+
+\def\!tfSetWidth
+ {\ifempty\!tfRowOfWidths % true if no prior "w" keys
+ \ifnum\!taColumnNumber>\zerocount % true if "w" key is to right of first "|"
+ \begingroup % RowOfWidths={\aligntab\omit || n copies of \aligntab\omit\aligntab#\omit}, where n = number of column to the left of this one
+ \scratchcounter\plusone
+ \aftergroup\edef
+ \aftergroup\!tfRowOfWidths
+ \aftergroup{%
+ \aftergroup\aligntab
+ \aftergroup\omit
+ \!thLoop
+ \ifnum \scratchcounter<\!taColumnNumber
+ \advance\scratchcounter\plusone
+ \aftergroup\!tfAOAO
+ \repeat
+ \aftergroup}%
+ \endgroup
+ \fi
+ \fi
+ \ifx[\tempstring % \!tgGetValue sets \tempstring = token after w
+ \expandafter\!tfSetWidthText
+ \else
+ \expandafter\!tfSetWidthValue
+ \fi}
+
+\def\!tfAOAO{\aligntab\omit\aligntab\omit}
+
+\def\!tfSetWidthText[#1]%
+ {\def\!tfWidthText{#1}%
+ \doreadtableformatkeys}
+
+\def\!tfSetWidthValue
+ {\!taMinimumColumnWidth
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue \tablecolumnwidthfactor \else \!tgValue \fi \d_tabl_table_column_width_unit
+ \else
+ \!tgValue
+ \fi
+ \let\!tfWidthText\empty % Override possible prior `w[sample entry]'
+ \doreadtableformatkeys}
+
+\def\!tfSetTabskip
+ {\ifnum\!tgCode=\plusone
+ \scratchskip\s_tabl_table_inter_column_space_unit
+ \multiply\scratchskip \ifempty\!tgValue\tableintercolumnspacefactor\else\!tgValue\fi
+ \else
+ \scratchskip\!tgValue
+ \fi
+ \divide\scratchskip\plustwo
+ \ifnum\!taColumnNumber=\zerocount
+ %\!thToksEdef\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}%
+ \normalexpanded{\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}}%
+ \else
+ %\!thToksEdef\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}%
+ \normalexpanded{\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}}%
+ \fi
+ \if!taOnceOnlyTabskip\else
+ \!taLastRegularTabskip\scratchskip % Remember this Tabskip, for possible
+ \fi % restoration after a subsequent"OnceOnly"
+ \doreadtableformatkeys}
+
+\def\!tfSetVrule
+ {\!thToksEdef\!taRuleColumnTemplate
+ {\hfil
+ \vrule
+ \noexpand\s!width
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \c_tabl_table_vrule_thickness_factor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue
+ \fi
+ \alignmark\alignmark\alignmark\alignmark
+ \hfil
+ \the\!taRuleColumnTemplate}%
+ \!tfAdjoinPriorColumn}
+
+\def\!tfSetAlternateVrule
+ {\afterassignment\!tfSetAlternateA\scratchtoks}
+
+\def\!tfSetAlternateA
+ {\!thToksEdef\!taRuleColumnTemplate{\the\scratchtoks\the\!taRuleColumnTemplate}%
+ \!tfAdjoinPriorColumn}
+
+\def\!tfAdjoinPriorColumn
+ {\ifnum\!taColumnNumber=\zerocount
+ \!taPreamble=\!taRuleColumnTemplate % New \tabskip may have been added
+ \else
+ \ifempty\!tfRowOfWidths\else % no "w" keys specified yet, not even this col
+ \!tfUpdateRowOfWidths
+ \fi
+ \!thToksEdef\!taDataColumnTemplate{\the\!taLeftGlue\the\!taDataColumnTemplate\the\!taRightGlue}%
+ \!thToksEdef\!taPreamble{\the\!taPreamble\aligntab\the\!taDataColumnTemplate\aligntab\the\!taRuleColumnTemplate}%
+ \fi
+ \advance\!taColumnNumber\plusone
+ \if!taOnceOnlyTabskip
+ \!thToksEdef\!taDataColumnTemplate{\alignmark\alignmark\alignmark\alignmark\tabskip\the\!taLastRegularTabskip}%
+ \else
+ \!taDataColumnTemplate{\alignmark\alignmark}%
+ \fi
+ \!taRuleColumnTemplate\emptytoks
+ \!taLeftGlue{\hfil}%
+ \!taRightGlue{\hfil}%
+ \!taMinimumColumnWidth\zeropoint
+ \let\!tfWidthText\empty
+ \!taOnceOnlyTabskipfalse
+ \doreadtableformatkeys}
+
+\def\!tfUpdateRowOfWidths
+ {\ifempty\!tfWidthText\else
+ \!tfComputeMinColWidth
+ \fi
+ \edef\!tfRowOfWidths
+ {\!tfRowOfWidths
+ \aligntab
+ \omit
+ \ifdim \!taMinimumColumnWidth>\zeropoint
+ \hskip \the\!taMinimumColumnWidth
+ \fi
+ \aligntab
+ \omit}}
+
+\def\!tfComputeMinColWidth
+ {\setbox\scratchbox\vbox
+ {\ialign{% Plain's initialized \halign; \tabskip=0pt \everycr={}
+ \span\the\!taDataColumnTemplate\cr
+ \!tfWidthText\cr}}%
+ \!taMinimumColumnWidth\wd\scratchbox}
+
+\def\!tfFinishFormat
+ {\!thToksEdef\!taPreamble{%
+ \alignmark\alignmark\alignmark\alignmark\tabskip\tablelefttabskip
+ \aligntab
+ \the\!taPreamble\tabskip\tablerighttabskip
+ \aligntab
+ \alignmark\alignmark\alignmark\alignmark\tabskip\zeropoint\cr}
+ \!taBeginFormatfalse
+ \!ttDoHalign}
+
+\def\tabl_table_reformat[#1]% will become local
+ {\omit
+ \!taDataColumnTemplate{\alignmark\alignmark}%
+ \!taLeftGlue\emptytoks
+ \!taRightGlue\emptytoks
+ \begingroup
+ \tabl_table_use_bar
+ \expanded{\endgroup\noexpand\doreadtableformatkeys#1]}}% appear in a \tabl_table_reformat cmd; this is here as a safeguard.
+
+\appendtoks
+ \enforced\let\ReFormat\tabl_table_reformat
+\to \everytable
+
+\def\!tfEndReFormat
+ {\!tfReFormat}
+
+\appendtoks \tabl_table_paralignment \to \everytableparbox
+
+\def\!tfReFormat#1%
+ {\the \!taLeftGlue
+ \vbox{\forgetall\ialign{\span\the\!taDataColumnTemplate\cr#1\cr}}%
+ \the \!taRightGlue
+ \kern\zeropoint} % prevents \unskip / really needed
+
+\def\!tgGetValue#1%
+ {\def\!tgReturn{#1}%
+ \futurelet\tempstring\!tgCheckForParen}
+
+\def\!tgCheckForParen%
+ {\ifx\tempstring (%
+ \expandafter \!tgDoParen
+ \else
+ \expandafter \!tgCheckForSpace
+ \fi}
+
+\def\!tgDoParen(#1)%
+ {\def\!tgCode{2}% will be expanded
+ \def\!tgValue{#1}%
+ \!tgReturn}
+
+\def\!tgCheckForSpace
+ {\def\!tgCode{1}%
+ \let\!tgValue\empty
+ \ifx\tempstring\!thSpaceToken
+ \expandafter\!tgReturn
+ \else
+ \expandafter\!tgCheckForDigit
+ \fi}
+
+\def\!tgCheckForDigit % less tokens: (could be an ifcsname)
+ {\donetrue
+ \ifx 0\tempstring \orelse \ifx 1\tempstring \orelse
+ \ifx 2\tempstring \orelse \ifx 3\tempstring \orelse
+ \ifx 4\tempstring \orelse \ifx 5\tempstring \orelse
+ \ifx 6\tempstring \orelse \ifx 7\tempstring \orelse
+ \ifx 8\tempstring \orelse \ifx 9\tempstring \else
+ \donefalse
+ \fi
+ \ifdone
+ \expandafter\!tgGetNumber
+ \else
+ \expandafter\!tgReturn
+ \fi}
+
+% \def\!tgCheckForDigit % does not work
+% {\relax\doifnumberelse\tempstring\!tgGetNumber\!tgReturn}
+
+\def\!tgGetNumber {\afterassignment\!tgGetNumberA\scratchcounter=}
+\def\!tgGetNumberA{\edef\!tgValue{\the\scratchcounter}\!tgReturn}
+
+\def\!tgSetUpParBox
+ {\normalexpanded
+ {\noexpand \doreadtableformatkeys
+ b{\tabl_table_begin_par_box
+ {\ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \tablecolumnwidthfactor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_column_width_unit
+ \else
+ \!tgValue
+ \fi}}%
+ a{\tabl_table_end_par_box}}}
+
+\def\!tgInsertKern
+ {\edef\tempstring
+ {\kern
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \tablekernfactor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_kern_unit
+ \else
+ \!tgValue
+ \fi}%
+ \edef\tempstring
+ {\noexpand\doreadtableformatkeys
+ \ifconditional\c_tabl_table_spacing_left
+ b{\tempstring}
+ \fi
+ \ifconditional\c_tabl_table_spacing_right
+ a{\tempstring}
+ \fi}%
+ \tempstring}
+
+\def\newtableformatkey #1{\setvalue{!tk<\string#1>}}
+\def\doreadtableformatkeys#1{\getvalue{!tk<\string#1>}}
+
+% Key "b": b{TOKENS} adds TOKENS to the left of (before) the template
+
+\newtableformatkey b#1%
+ {\expandafter\!tkJoin\expandafter{\the\!taDataColumnTemplate}{#1}%
+ \doreadtableformatkeys}
+
+\def\!tkJoin#1#2%
+ {\!taDataColumnTemplate{#2#1}}%
+
+% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template
+
+\newtableformatkey a#1%
+ {\toksapp\!taDataColumnTemplate{#1}%
+ \doreadtableformatkeys}
+
+% Key "\{": Enclose template in braces.
+
+\newtableformatkey \{%
+ {\!taDataColumnTemplate=\expandafter{\expandafter{\the\!taDataColumnTemplate}}%
+ \doreadtableformatkeys}
+
+% Key "*": "*{N}{KEY LETTERS}" is equivalent to specifying
+% <KEY LETTERS> N times.
+% KEY LETTERS may contain further * specifications
+
+\newtableformatkey *#1#2%
+ {\scratchcounter=#1\relax
+ \scratchtoks\emptytoks
+ \!thLoop
+ \ifnum\scratchcounter>\zerocount
+ \toksapp\scratchtoks{#2}%
+ \advance\scratchcounter\minusone
+ \repeat
+ \expandafter\doreadtableformatkeys\the\scratchtoks}
+
+% Key "\LeftGlue": Specifies the glue (usually \hfil, or nothing) to be
+% added to extreme left of the template to position a column
+
+\newtableformatkey \LeftGlue#1%
+ {\!taLeftGlue{#1}%
+ \doreadtableformatkeys}
+
+\newtableformatkey \RightGlue#1%
+ {\!taRightGlue{#1}%
+ \doreadtableformatkeys}
+
+\newtableformatkey c%
+ {\prependtoks\raggedcenter\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\hfil}
+
+\newtableformatkey l%
+ {\prependtoks\raggedright\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\empty \RightGlue\hfil}
+
+\newtableformatkey r%
+ {\prependtoks\raggedleft\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty}
+
+\newtableformatkey x%
+ {\prependtoks\notragged\to\!taDataColumnTemplate
+ \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty}
+
+% Key "k": Adds kerns to left and right of "#" This key and the two below use Plain
+% TeX's \if@h as if it were \if@left, and \if@v as if it were \if@right. Table
+% making goes on in a group, so even in the unlikely circumstance that a \phantom
+% is currently under construction, there's no problem.
+
+\newtableformatkey k%
+ {\settrue\c_tabl_table_spacing_left
+ \settrue\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "i": Adds a kern to the left of "#"
+
+\newtableformatkey i%
+ {\settrue\c_tabl_table_spacing_left
+ \setfalse\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "j": Adds a kern to the right of "#"
+
+\newtableformatkey j%
+ {\setfalse\c_tabl_table_spacing_left
+ \settrue\c_tabl_table_spacing_right
+ \!tgGetValue{\!tgInsertKern}}
+
+% Key "n": numeric item , non-math mode.
+
+\newtableformatkey n%
+ {\def\!tnStyle{}%
+ \futurelet\!tnext\!tnTestForBracket}
+
+% Key "N": numeric item, math mode.
+
+\newtableformatkey N%
+ {\def\!tnStyle{$}%
+ \futurelet\!tnext\!tnTestForBracket}
+
+% Key "m": Math mode.
+
+\newtableformatkey m%
+ {\doreadtableformatkeys b{\normalstartimath} a{\normalstopimath}}
+
+% Key "M": Displaymath mode.
+
+\newtableformatkey M%
+ {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}}
+
+% Key "\m": Template ${}#\hfil$
+
+\newtableformatkey \m%
+ {\doreadtableformatkeys l b{{}} m}
+
+% Key "\M": Template $\displaystyle{{}#\hfil}$
+
+\newtableformatkey \M%
+ {\doreadtableformatkeys l b{{}} M}
+
+% Key "f": Set font (E.g., f\it sets up italic font (assuming \it
+% has its usual meaning)
+
+\newtableformatkey f#1%
+ {\doreadtableformatkeys b{#1}}
+
+\newtableformatkey B{\doreadtableformatkeys f\bf} % Key "B": abbreviation for f\bf
+\newtableformatkey I{\doreadtableformatkeys f\it} % Key "I": abbreviation for f\it
+\newtableformatkey S{\doreadtableformatkeys f\sl} % Key "S": abbreviation for f\sl
+\newtableformatkey R{\doreadtableformatkeys f\rm} % Key "R": abbreviation for f\rm
+\newtableformatkey T{\doreadtableformatkeys f\tt} % Key "T": abbreviation for f\tt
+
+% Key "p": ParBox
+
+\newtableformatkey p%
+ {\!tgGetValue{\!tgSetUpParBox}}
+
+% Key "w": minimum column width
+
+\newtableformatkey w%
+ {\!tkTestForBeginFormat w{\!tgGetValue{\!tfSetWidth}}}
+
+% Key "s": Set tabskip for the inter-column space to the right of the current
+% column, and all subsequent spaces, until overriden by a new "s" or "o" key.
+
+\newtableformatkey s%
+ {\!taOnceOnlyTabskipfalse % in case same column has a prior "o" key
+ \!tkTestForBeginFormat t{\!tgGetValue{\!tfSetTabskip}}}
+
+% Key "o": Apply the \tabskip stated for this column ONLY to the inter-column space
+% just to the right of this column; restore the the previous \tabskip for
+% subsequent columns.
+
+\newtableformatkey o%
+ {\!taOnceOnlyTabskiptrue
+ \!tkTestForBeginFormat o{\!tgGetValue{\!tfSetTabskip}}}
+
+% Key "|": Standard rule column designator
+
+\newtableformatkey |%
+ {\!tkTestForBeginFormat |{\!tgGetValue{\!tfSetVrule}}}
+
+% Key "\|": Non-standard rule column designator
+
+\newtableformatkey \|%
+ {\!tkTestForBeginFormat \|{\!tfSetAlternateVrule}}
+
+% Key ".": PERIOD -- end of \tabl_table_begin_format section.
+
+\newtableformatkey .%
+ {\!tkTestForBeginFormat.{\!tfFinishFormat}}
+
+% Key "\doendtableformat": Equivalent to "."
+
+\newtableformatkey \doendtableformat
+ {\!tkTestForBeginFormat\doendtableformat{\!tfFinishFormat}}
+
+% Key "]": End of \tabl_table_reformat section
+
+\newtableformatkey ]%
+ {\!tkTestForReFormat ] \!tfEndReFormat}
+
+% TEST FOR BEGIN FORMAT{<Key>}{Intended Action}: This test is run on keys that can
+% only be used by \tabl_table_begin_format --- "s", "o", "|", "\|", "w", ".", and
+% "\doendtableformat".
+
+\def\!tkTestForBeginFormat#1#2%
+ {\if!taBeginFormat
+ \def\tempstring{#2}%
+ \expandafter\tempstring
+ \else
+ \toks0={#1}%
+ \toks2=\expandafter{\string\tabl_table_reformat}%
+ \expandafter\!tkImproperUse
+ \fi}
+
+% TEST FOR RE FORMAT{<Key>}{Intended Action}: This test is run on the key "]",
+% which can only be used by \tabl_table_reformat.
+
+\def\!tkTestForReFormat#1#2%
+ {\if!taBeginFormat
+ \toks0={#1}%
+ \toks2=\expandafter{\string\tabl_table_begin_format}%
+ \expandafter\!tkImproperUse
+ \else
+ \def\tempstring{#2}%
+ \expandafter\tempstring
+ \fi}
+
+% NOTE: THE SPACE BETWEEN A NUMERIC ENTRY AND THE FOLLOWING '|', '"', OR '\|' IS
+% MANDATORY. EMPTY NUMERIC ENTRIES ARE NOT ALLOWED: USE '{}' OR '\omit' INSTEAD.
+
+\def\!tnTestForBracket
+ {\ifx[\!tnext
+ \expandafter\!tnGetArgument
+ \else
+ \expandafter\!tnGetCode
+ \fi}
+
+% GET CODE: E.g. "4", or "4.0", "0.4", or "10.2"
+
+\def\!tnGetCode#1 %
+ {\!tnConvertCode #1..!}
+
+% CONVERT CODE: E.g. converts above to [0000], [0000.], [.0000], [0000000000.00]
+
+\def\!tnConvertCode #1.#2.#3!%
+ {\begingroup
+ \aftergroup\edef \aftergroup\tempstring \aftergroup{%
+ \aftergroup[%
+ \scratchcounter#1\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \def\tempstring{#3}%
+ \ifempty\tempstring\else
+ \aftergroup.
+ \scratchcounter#2\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \fi
+ \aftergroup]\aftergroup}%
+ \endgroup\relax
+ \expandafter\!tnGetArgument\tempstring}
+
+% GET ARGUMENT: [<sample left field> <optional .<sample right field>>
+
+\def\!tnGetArgument[#1]%
+ {\!tnMakeNumericTemplate\!tnStyle#1..!}
+
+% MAKE NUMERIC TEMPLATE
+
+\def\!tnMakeNumericTemplate#1#2.#3.#4!% #1=<empty> or $
+ {\def\tempstring{#4}%
+ \ifempty\tempstring
+ \!taDimenC\zeropoint
+ \else
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1.#3#1}%
+ \!taDimenC\wd\scratchbox
+ \fi
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}%
+ \!thToksEdef\!taDataColumnTemplate
+ {\noexpand\!tnSetNumericItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}%
+ \the\!taDataColumnTemplate}% Might have tabskip glue in here
+ \doreadtableformatkeys}
+
+% SET NUMERIC ITEM
+
+\def\!tnSetNumericItem #1#2#3#4 %
+ {\!tnSetNumericItemA {#1}{#2}{#3}#4..!}
+
+\def\!tnSetNumericItemA #1#2#3#4.#5.#6!%
+ {\def\tempstring{#6}%
+ \hbox to #1{\hss \mathsurround\zeropoint #3#4#3}%
+ \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint #3.#5#3\fi\hss}}
+
+% extensions
+
+\newtableformatkey q%
+ {\let\!tqStyle\empty
+ \futurelet\!tnext\!tqTestForBracket}
+
+\newtableformatkey Q%
+ {\def\!tqStyle{$}%
+ \futurelet\!tnext\!tqTestForBracket}
+
+\def\!tqTestForBracket
+ {\ifx[\!tnext
+ \!thx\!tqGetArgument
+ \else
+ \!thx\!tqGetCode
+ \fi}
+
+\def\!tqGetCode#1 % note the blank
+ {\!tqConvertCode #1,,!}
+
+\def\!tqConvertCode #1,#2,#3!%
+ {\begingroup
+ \aftergroup\edef
+ \aftergroup\tempstring
+ \aftergroup{%
+ \aftergroup[%
+ \scratchcounter#1\relax
+ \!thLoop
+ \ifnum \scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \def\tempstring{#3}%
+ \ifempty\tempstring\else
+ \aftergroup,
+ \scratchcounter#2\relax
+ \!thLoop
+ \ifnum\scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \aftergroup0
+ \repeat
+ \fi
+ \aftergroup]\aftergroup}%
+ \endgroup\relax
+ \!thx\!tqGetArgument\tempstring}
+
+\def\!tqGetArgument[#1]%
+ {\!tqMakeQuantityTemplate\!tqStyle#1,,!}
+
+\def\!tqMakeQuantityTemplate#1#2,#3,#4!% #1=<empty> or $
+ {\def\tempstring{#4}%
+ \ifempty\tempstring
+ \!taDimenC\zeropoint
+ \else
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1,#3#1}%
+ \!taDimenC\wd\scratchbox
+ \fi
+ \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}%
+ \!thToksEdef\!taDataColumnTemplate
+ {\noexpand\!tqSetQuantityItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}%
+ \the\!taDataColumnTemplate}%
+ \doreadtableformatkeys}
+
+\def\!tqSetQuantityItem #1#2#3#4 %
+ {\!tqSetQuantityItemA{#1}{#2}{#3}#4,,!}
+
+\def\!tqSetQuantityItemA #1#2#3#4,#5,#6!%
+ {\def\tempstring{#6}%
+ \hbox to #1{\hss\mathsurround\zeropoint#3#4#3}%
+ \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint#3,#5#3\fi\hss}}
+
+% \Enlarge<extra height><extra depth><original>
+% \enlarge<multiple for extra height><multiple for extra depth><original>
+
+\def\tabl_table_Enlarge#1#2%
+ {% 3rd argument is picked up later
+ % #1=extra height
+ % #2=extra depth
+ \!taDimenA=#1\relax
+ \!taDimenB=#2\relax
+ \let\!TsSpaceFactor\empty
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!TsEnlargeMath
+ \else
+ \expandafter\!TsEnlargeOther
+ \fi}
+
+\def\!TsEnlargeOther#1%
+ {\ifhmode
+ \setbox\scratchbox\hbox{#1\xdef\!TsSpaceFactor{\spacefactor\the\spacefactor}}%
+ \else
+ \setbox\scratchbox\hbox{#1}%
+ \fi
+ \!TsFinishEnlarge}
+
+\def\!TsEnlargeMath#1#2%
+ {\setbox\scratchbox\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}%
+ \!TsFinishEnlarge}
+
+\def\!TsFinishEnlarge
+ {\ht\scratchbox\dimexpr\ht\scratchbox+\!taDimenA\relax
+ \dp\scratchbox\dimexpr\dp\scratchbox+\!taDimenB\relax
+ \box\scratchbox
+ \!TsSpaceFactor\relax}
+
+\def\tabl_table_enlarge#1#2% 3rd argument is picked up later
+ {\tabl_table_Enlarge{#1\d_tabl_table_strut_unit}{#2\d_tabl_table_strut_unit}}
+
+\appendtoks
+ \enforced\let\enlarge\tabl_table_enlarge
+ \enforced\let\Enlarge\tabl_table_Enlarge
+\to \everytable
+
+% BEGIN TABLE
+
+\let\tabl_table_standard_end\relax
+
+\def\tabl_table_standard_begin[#1]% \!ttBeginTable (always argument)
+ {\if#1u% unboxed table
+ \ifmmode
+ \let\tabl_table_standard_end\relax % user had better be in display math mode and have only one table at the outer level
+ \else % user had better be in vertical mode
+ \bgroup
+ \let\tabl_table_standard_end\egroup
+ \fi
+ \else
+ \hbox\bgroup
+ \def\tabl_table_standard_end{\egroup\egroup}%
+ \if#1t%
+ \vtop
+ \orelse\if#1b%
+ \vbox
+ \else
+ \def\tabl_table_standard_end{\egroup\normalstopimath\egroup}%
+ \scratchtoks\everymath
+ \everymath\emptytoks
+ \normalstartimath
+ \everymath\scratchtoks
+ \vcenter
+ \fi
+ \bgroup % for the \vtop, \vbox, or \vcenter
+ \fi
+ \advance\!taRecursionLevel\plusone
+ \let\!ttRightGlue\relax
+ \everycr\emptytoks
+ \ifnum\!taRecursionLevel=\plusone
+ \the\everytable
+ \fi}
+
+\bgroup \catcode\tildeasciicode\activecatcode
+
+ \appendtoks
+ \catcode\barasciicode\activecatcode
+ \enforced\protected\def ~{\kern.5em}%
+ \enforced\protected\def\\{\ifhmode\space\else\par\fi}%
+ \to \everytable
+
+\egroup
+
+\let\!ttRightGlue\relax % This may be changed, in a group, by \JustCenter, etc
+
+% DO HALIGN: Invoked by END FORMAT (or the key ".")
+
+\let\tabl_table_restore_lineskips\relax
+
+\def\!ttDoHalign
+ {\edef\tabl_table_restore_lineskips
+ {\baselineskip \the\baselineskip
+ \lineskiplimit\the\lineskiplimit
+ \lineskip \the\lineskip
+ \tabskip \the\tabskip
+ \relax}%
+ \baselineskip \zeropoint
+ \lineskiplimit\zeropoint
+ \lineskip \zeropoint
+ \tabskip \zeropoint
+ \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}%
+ % we are not in sync so:
+ \synchronizedisplaydirection
+ \synchronizeinlinedirection
+ \halign
+ \usedirectionparameterreverse\directtablesparameter
+ \ifempty\p_tabl_table_textwidth \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi
+ %\the\!taTableSpread
+ \bgroup
+ \span
+ \the\!taPreamble
+ \ifempty\!tfRowOfWidths\else
+ \!tfRowOfWidths\cr
+ \fi}
+
+% END TABLE
+
+\def\tabl_table_normal_end
+ {\egroup % finishes the \halign
+ \tabl_table_standard_end} % closes off the table envirnoment set up by \tablestandardbegin
+
+\def\tabl_table_normal_line_ending
+ {\cr}
+
+\def\tabl_table_normal_line_format#1#2%
+ {\vrule
+ \s!width \zeropoint
+ \s!height\dimexpr\tablestrutheightfactor\d_tabl_table_strut_unit+#1\d_tabl_table_strut_unit\relax
+ \s!depth \dimexpr\tablestrutdepthfactor \d_tabl_table_strut_unit+#2\d_tabl_table_strut_unit\relax
+ \relax
+ \cr}
+
+% INSERT VRULE
+
+\newcount\c_tabl_table_n_of_vrules \c_tabl_table_n_of_vrules\plusone
+
+\let\m_tabl_table_vrule_color\empty
+\let\m_tabl_table_hrule_color\empty
+
+\def\do!ttInsertVrule
+ {\vrule\s!width
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \c_tabl_table_vrule_thickness_factor
+ \else
+ \!tgValue
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue
+ \fi
+ \hskip.125\emwidth\relax}
+
+\def\tabl_table_normal_line_simple_bar
+ {\unskip\!ttRightGlue\aligntab\aligntab}
+
+\def\tabl_table_normal_line_complex_bar
+ {\unskip\!ttRightGlue\aligntab\omit
+ \hfil
+ \ifempty\m_tabl_table_vrule_color\else
+ \switchtocolor[\m_tabl_table_vrule_color]%
+ \fi
+ \ifcase\c_tabl_table_n_of_vrules\or
+ \do!ttInsertVrule
+ \unskip
+ \else
+ \dorecurse\c_tabl_table_n_of_vrules\do!ttInsertVrule
+ \global\c_tabl_table_n_of_vrules\plusone
+ \unskip
+ \fi
+ \glet\m_tabl_table_vrule_color\empty
+ \hfil
+ \aligntab}
+
+\def\tabl_table_normal_no_bar
+ {\unskip\!ttRightGlue\aligntab\omit\aligntab}
+
+\def\tabl_table_normal_single_rule
+ {\aligntab\tabl_table_normal_long_rule\aligntab}
+
+\def\tabl_table_normal_multi_rule
+ {\aligntab\tabl_table_use\c_tabl_table_drule_span\tabl_table_normal_long_rule\aligntab}
+
+% USE
+
+\def\tabl_table_use#1%
+ {\ifnum#1>\plusone
+ \omit
+ \global\setfalse\c_tabl_table_is_division % added
+ \scratchcounter\currenttablecolumn % added
+ \advance\scratchcounter #1% % added
+ \advance\scratchcounter \minusone % added
+ \def\next % added
+ {\global\advance\currenttablecolumn #1% % added
+ \global\advance\currenttablecolumn \minusone % added
+ \scratchcounter#1%
+ \advance\scratchcounter \minusone
+ \advance\scratchcounter \scratchcounter
+ \!thLoop
+ \ifnum\scratchcounter>\plusone
+ \spanomit \advance\scratchcounter\minusone
+ \repeat
+ \span}%
+ \else % added
+ \def\next % conflicts with possible next \omit % added
+ {\global\advance\currenttablecolumn \plusone}%% added
+ \fi
+ \next} % added
+
+\def\tabl_table_Use#1[%
+ {\tabl_table_use{#1}%
+ \tabl_table_reformat[}
+
+\appendtoks
+ \enforced\let\use\tabl_table_use
+ \enforced\let\Use\tabl_table_Use
+\to \everytable
+
+% rules
+
+\def\tabl_table_normal_full_rule
+ {\noalign\bgroup
+ \!ttGetHalfRuleThickness
+ \scratchdistance\directtablesparameter\c!openup
+ \ifzeropt\scratchdistance\else\kern\scratchdistance\fi
+ \hrule\s!height\scratchdimen\s!depth\scratchdimen
+ \ifzeropt\scratchdistance\else\kern\scratchdistance\fi
+ \egroup}
+
+\def\tabl_table_normal_short_rule % was: \!ttShortHrule
+ {\omit
+ \!ttGetHalfRuleThickness
+ \ifempty\m_tabl_table_hrule_color\else
+ \switchtocolor[\m_tabl_table_hrule_color]% see *DL*
+ \fi
+ \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill
+ \emptyhbox
+ \ignorespaces}
+
+\def\tabl_table_normal_long_rule % was: \!ttLongHrule
+ {\omit\span
+ \omit\span
+ \tabl_table_normal_short_rule}
+
+\def\!ttGetHalfRuleThickness
+ {\scratchdimen\dimexpr
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \c_tabl_table_hrule_thickness_factor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_line_thickness_unit
+ \else
+ \!tgValue % user-specified dimension
+ \fi
+ \divide\scratchdimen\plustwo}
+
+% \emptyhbox prevents \unskip
+
+\def\tabl_table_Left #1{#1\hfill\emptyhbox}
+\def\tabl_table_Center#1{\hfill#1\hfill\emptyhbox}
+\def\tabl_table_Right #1{\hfill#1}
+
+\def\tabl_table_OpenUp#1#2%
+ {\edef\tablestrutheightfactor{\withoutpt\the\dimexpr\tablestrutheightfactor\points+#1\points}%
+ \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr\tablestrutdepthfactor \points+#2\points}}
+
+% SetTableToWidth -> textwidth=dimension [to dimension]
+% Expand -> textwidth=max [to \hsize]
+% WidenTableBy -> [spread #1]
+% \tablelefttabskip\zeropoint\s!plus1\s!fill
+% \tablerighttabskip\tablelefttabskip
+% LongLines -> [spread \hsize]
+
+\def\tabl_table_JustLeft {\omit\let\!ttRightGlue\hfill}
+\def\tabl_table_JustCenter{\omit\hfill\emptyhbox\let\!ttRightGlue\hfill}
+\def\tabl_table_JustRight {\omit\hfill\emptyhbox}
+
+\def\tabl_table_Smash
+ {\relax
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!thDoMathVCS
+ \else
+ \expandafter\!thDoVCS
+ \fi}
+
+\def\!thDoVCS#1%
+ {\setbox\zerocount\hbox{#1}%
+ \!thFinishVCS}
+
+\def\!thDoMathVCS#1#2%
+ {\setbox\zerocount\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}%
+ \!thFinishVCS}
+
+\def\!thFinishVCS
+ {\vpack to\zeropoint{\vss\box\zerocount\vss}}
+
+\def\tabl_table_Raise
+ {\def\!thSign{+}%
+ \!tgGetValue\!thSetDimen}
+
+\def\tabl_table_Lower
+ {\def\!thSign{-}%
+ \!tgGetValue\!thSetDimen}
+
+\def\!thSetDimen
+ {\ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \!taDimenA\tablestrutheightfactor\d_tabl_table_strut_unit
+ \advance\!taDimenA\tablestrutdepthfactor\d_tabl_table_strut_unit
+ \divide\!taDimenA\plustwo
+ \else
+ \!taDimenA\!tgValue\d_tabl_table_strut_unit
+ \fi
+ \else
+ \!taDimenA\!tgValue
+ \fi
+ \!taDimenA\!thSign\!taDimenA\relax
+ \ifmmode
+ \expandafter\mathpalette
+ \expandafter\!thDoMathRaise
+ \else
+ \expandafter\!thDoSimpleRaise
+ \fi}
+
+\def\!thDoSimpleRaise#1%
+ {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{#1}}%
+ \!thFinishRaise} % From Plain TeX: \ht0=0pt \dp0=0pt \box0
+
+\def\!thDoMathRaise#1#2%
+ {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}}%
+ \!thFinishRaise}
+
+\def\!thFinishRaise
+ {\ht\zerocount\zeropoint
+ \dp\zerocount\zeropoint
+ \box\zerocount}
+
+\def\tabl_table_BackSpace
+ {\!tgGetValue\!thKernBack}
+
+\def\!thKernBack
+ {\kern -
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \tablekernfactor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_kern_unit
+ \else
+ \!tgValue % user-specified dimension
+ \fi
+ \ignorespaces}
+
+\def\tabl_table_Vspace
+ {\noalign
+ \bgroup
+ \!tgGetValue\!thVspace}
+
+\def\!thVspace
+ {\vskip
+ \ifnum\!tgCode=\plusone
+ \ifempty\!tgValue
+ \tablevspacefactor
+ \else
+ \!tgValue % user-specified integer
+ \fi
+ \d_tabl_table_strut_unit
+ \else
+ \!tgValue % user-specified skip
+ \fi
+ \egroup} % Ends the \noalign
+
+\appendtoks
+ \enforced\let\JustLeft \tabl_table_JustLeft
+ \enforced\let\JustCenter \tabl_table_JustCenter
+ \enforced\let\JustRight \tabl_table_JustRight
+ \enforced\let\Smash \tabl_table_Smash
+ \enforced\let\Raise \tabl_table_Raise
+ \enforced\let\Lower \tabl_table_Lower
+ \enforced\let\BackSpace \tabl_table_BackSpace
+ \enforced\let\Vspace \tabl_table_Vspace
+ \enforced\let\OpenUp \tabl_table_OpenUp
+ \enforced\let\TableLeft \tabl_table_Left
+ \enforced\let\TableCenter\tabl_table_Center
+ \enforced\let\TableRight \tabl_table_Right
+\to \everytable
+
+%D \macros
+%D {inintable, ifsplittables}
+%D
+%D First we declare some variables. These show a bit what we are dealing with. First
+%D we introdoce some booleans that enable us, inside as well as outside this module,
+%D to determine in what mode we are.
+
+\newif\ifintable
+\newif\ifsplittables
+
+%D We show this feature in an example that also shows some of the basic table
+%D typesetting commands.
+%D
+%D \startbuffer
+%D \starttable[|||]
+%D \HL
+%D \VL first \VL second \VL\AR
+%D \HL
+%D \VL alfa \VL 1 \VL\AR
+%D \VL beta \VL 2 \VL\AR
+%D \VL gamma \VL 3 \VL\AR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D This table is specified as:
+%D
+%D \typebuffer
+%D
+%D This examples shows about the minimum of commands needed to typeset such a table.
+%D In this table, the \type {\AR} is automatically translated into the more
+%D primitive (but more verbose) commands \type {\SR}, \type {\FR}, \type {\MR} and
+%D \type {\LR} commands.
+%D
+%D \startbuffer
+%D \starttables[|||]
+%D \HL
+%D \VL first \VL second \VL\AR
+%D \HL
+%D \VL alfa \VL 1 \VL\AR
+%D \VL beta \VL 2 \VL\AR
+%D \VL gamma \VL 3 \VL\AR
+%D \HL
+%D \stoptables
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D Some simple color support is provided:
+%D
+%D \startbuffer
+%D \starttable[|c|c|]
+%D \HL
+%D \VL test \VL test \VL \SR
+%D \HL[green,5]
+%D \VL[red] test \VL test \VL \FR
+%D \VL test \VL[10,red] test \VL \MR
+%D \VL test \VL test \VL[10] \LR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{tabletemplate}
+
+\immutable\def\m!TABLE{TABLE}
+
+%D We already saw that the table macros report errors and provide automatic spacing.
+%D These features can only be implemented by keeping track of the state, often the
+%D last command on a row.
+
+\newconstant\tableforcestate
+\newconstant\tableactionstate
+
+\setnewconstant\tableunknownstate 0
+
+\setnewconstant\tableseparaterowstate 1
+\setnewconstant\tablefirstrowstate 2
+\setnewconstant\tablemidrowstate 3
+\setnewconstant\tablelastrowstate 4
+\setnewconstant\tablerulestate 5
+%setnewconstant\tableskipstate 6
+%setnewconstant\tableautorowstate 7
+
+\setnewconstant\tableforcefirstrowstate 1
+\setnewconstant\tableforcelastrowstate 2
+
+\newconstant\tablerowfactor
+\newconstant\TABLEendofrowdepth
+\newconstant\TABLEendofrowheight
+\newconstant\TABLEcr
+\newconstant\tablerowzero
+\newconstant\TABLEn
+
+%D We store these states using \type {constants}'s and like most variables, these
+%D are global ones. When needed, especially when we flush the backgrounds, we can
+%D temporary disable the assignment.
+
+\newconditional\tableactionstatepermitted
+
+\def\tabl_table_set_action#1{\ifconditional\tableactionstatepermitted\global\tableactionstate#1\fi}
+\def\tabl_table_set_force #1{\ifconditional\tableactionstatepermitted\global\tableforcestate #1\fi}
+
+%D To give an impression of what the (well documented) source of \TABLE\ looks like,
+%D we first implement an alternative for the numeric keys. The quantity keys
+%D (\type{q} and \type{Q}) support the more european way of writing numbers:
+%D
+%D \startnarrower
+%D 100.000.000,00 instead of 100,000,000.00
+%D \stopnarrower
+%D
+%D The next table shows how to use these keys. We use braces instead of brackets because
+%D we need brackets to specify the format.
+%D
+%D \starttyping
+%D \starttable{|q[00,000]|Q[00,00]|}
+%D \HL
+%D \VL -1,2 \VL 12,35 \VL\FR
+%D \VL 11,203 \VL 2,4 \VL\LR
+%D \HL
+%D \stoptable
+%D \stoptyping
+%D
+%D Although a more efficient implementation is possible |<|we can for instance share
+%D common macros|>| we just adapt a copy of the numeric ones. To permit double
+%D loading of this module, we check for the existence of one of the macros.
+%D
+%D To be compatible with the tabulate environment, we also support the \type {l},
+%D \type {c} and \type {r} keys for paragraph entries.
+%D
+%D All commands that are executed between rows are to be put in \type {\noalign}. We
+%D can however not verify if we (that is \TABLE) does or did not enter this mode. A
+%D moderate dirty but useful trick is using our own alternative:\footnote{Once one
+%D has entered the stage of redefining \TEX\ primitives, such hacks become a second
+%D nature. However, redefining \type {\omit} and \type{\span} is not that easy.}
+
+%D We no longer need this in \LUAMETATEX:
+%D
+%D \starttyping
+%D \aliased\let\tablenoalign \noalign
+%D \def\starttablenoalign{\noalign\bgroup}
+%D \let\stoptablenoalign \egroup
+%D \stoptyping
+
+%D \macros
+%D {starttable}
+%D
+%D The rest of this module is not easy to comprehend, mainly because we have to take
+%D care of:
+%D
+%D \startitemize[packed]
+%D \item \type{\startitemize[template]}
+%D \item \type{\startitemize{template}}
+%D \item \type{\startitemize[predefined]}
+%D \stopitemize
+%D
+%D as well as:
+%D
+%D \startitemize[continue]
+%D \item restart after table break
+%D \stopitemize
+%D
+%D The official specification of the start command is:
+%D
+%D \showsetup{starttable}
+
+\newconditional\c_tabl_table_repeat_head
+\newconditional\c_tabl_table_repeat_tail
+
+\permanent\tolerant\protected\def\starttable[#1]#*[#2]% preamble optional-settings
+ {\bgroup
+ \ifarguments\or\or
+ \setupcurrenttables[#2]%
+ \fi
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \edef\p_tabl_table_frame{\directtablesparameter\c!frame}%
+ \ifx\p_tabl_table_split\v!auto
+ \ifinsidesplitfloat
+ \let\p_tabl_table_split\v!yes
+ \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode
+ \fi
+ \fi
+ \ifx\p_tabl_table_split\v!yes
+ \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead
+ \expandafter\starttables
+ \orelse\ifx\p_tabl_table_split\v!repeat
+ \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead
+ \expandafter\starttables
+ \else
+ \enforced\let\stoptable\table_table_stop
+ \ifempty\p_tabl_table_frame
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \else
+ \startframedcontent[\p_tabl_table_frame]%
+ \fi
+ \postponenotes
+ \expandafter\tabl_table_first_stage
+ \fi[#1]}
+
+% We cannot define the stopper as \type {\protected} because lookahead in
+% alignments fail then, so we relax it and define it locally.
+
+\permanent\let\stoptable\relax
+
+\permanent\def\table_table_stop
+ {\tabl_tables_chuck_auto_row % before the tail, else noalign problem
+ \tabl_table_insert_tail
+ \noalign\bgroup
+ \glet\tabl_table_head\empty
+ \glet\tabl_table_tail\empty
+ \egroup
+ \tabl_table_finish
+ \ifempty\p_tabl_table_frame
+ \ifinsidefloat\else
+ \stopbaselinecorrection
+ \goodbreak % compensates all the nobreaks
+ \fi
+ \else
+ \stopframedcontent
+ \fi
+ \egroup}
+
+\permanent\def\table_table_stop_g
+ {\table_table_stop_s\egroup}
+
+%D Before we can grab the argument, we have to make sure that the \CATCODES\ are
+%D set. The first stage takes care of that.
+
+\def\tabl_table_first_stage
+ {\bgroup
+ \global\intabletrue
+ \tabl_table_second_stage}
+
+%D \macros
+%D {definetabletemplate}
+%D
+%D The complex (and main) start macro first takes care of the predefined case. Such
+%D a predefined setup looks like:
+%D
+%D \starttyping
+%D \definetabletemplate[test][|||]
+%D
+%D \starttable[test]
+%D \VL test \VL test \VL\AR
+%D \VL test \VL test \VL\AR
+%D \VL test \VL test \VL\AR
+%D \stoptable
+%D \stoptyping
+%D
+%D The implementation of the definition macro is not that complicated:
+
+\installcorenamespace{tablehead}
+\installcorenamespace{tabletail}
+
+\permanent\protected\def\definetabletemplate % to be redone
+ {\bgroup
+ \catcode\barasciicode\othercatcode
+ \tabl_table_define_template}
+
+\tolerant\def\tabl_table_define_template[#1]#*[#2]#*[#3]#*[#4]%
+ {\ifarguments\or\else
+ \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}%
+ \fi
+ \egroup}
+
+\def\tabl_table_use_template#1#2#3%
+ {\gdef\tabl_table_head{\begincsname\??tablehead#2\endcsname}%
+ \gdef\tabl_table_tail{\begincsname\??tabletail#3\endcsname}%
+ \tabl_table_second_stage[#1]}
+
+%D The optional third and fourth arguments define which table head and tail to use.
+%D
+%D \starttyping
+%D \definetabletemplate[test][|||][before][after]
+%D \stoptyping
+%D
+%D This also means that one can define table heads and tails by name!
+%D
+%D \starttyping
+%D \starttablehead[before]
+%D \HL \VL first \VL second \VL \SR \HL
+%D \stoptablehead
+%D \stoptyping
+%D
+%D Templates defined this way get protected names, that cannot conflict with
+%D existing commands.
+%D
+%D \showsetup{definetabletemplate}
+%D
+%D The second half of the next macro prepares table
+%D splitting.
+
+\def\tabl_table_insert_head
+ {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometablehead}%
+ \tabl_table_head
+ \noalign{\global\setfalse\preventtablebreak}}
+
+\def\tabl_table_insert_tail
+ {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometabletail}%
+ \tabl_table_tail
+ \noalign{\global\setfalse\preventtablebreak}}
+
+% \def\doverysimpletableHL % todo
+% {\noalign{\normalexpanded{\noexpand\tabl_table_normal_full_rule\m_tabl_table_HLheight}}
+
+\def\tabl_table_restart_indeed#1%
+ {\gdef\tabl_table_restart{#1}%
+ \tabl_table_restart
+% \noalign{\globalpushmacro\simpletableHL\glet\simpletableHL\doverysimpletableHL}%
+ \tabl_table_insert_head
+ \ifsplittables \ifconditional \c_tabl_table_repeat_tail
+ \noalign{\goodbreak}%
+ \tabl_table_insert_tail
+ \noalign{\goodbreak}%
+ \fi \fi
+% \noalign{\globalpopmacro\simpletableHL}%
+ }
+
+\bgroup \catcode\barasciicode\othercatcode
+
+\gdef\tabl_table_second_stage[#1]% brr nested mess
+ {\bgroup
+ \tabl_table_use_bar
+ \global\setfalse\tableactionstatepermitted
+ \global\setfalse\hassometablehead
+ \global\setfalse\hassometabletail
+ \expanded{\doifelseinstring{|}{#1}}
+ {\xdef\tabl_table_restart{\noexpand\tabl_table_restart_indeed{\noexpand\tabl_table_third_stage{#1}}}}
+ {\doifelsedefined{\??tabletemplate#1}
+ {\gdef\tabl_table_restart{\getvalue{\??tabletemplate#1}}}
+ {\gdef\tabl_table_restart{\tabl_table_restart_indeed{\getvalue{#1}}}}}%
+ \egroup
+ \tabl_table_restart}
+
+\egroup
+
+%D The third stage involves a lot of (re)sets, which we will explain later.
+
+\appendtoks
+ \fixedspaces
+ \enforced\let\_\normalunderscore
+\to \everytable
+
+%D Now we can start the table.
+
+\newtoks\localtabledefinitions
+
+\def\tabl_table_third_stage#1%
+ {\global\settrue\tableactionstatepermitted
+ \tabl_table_set_action\tableunknownstate
+ \tabl_table_set_force\tableunknownstate
+ \tabl_table_resetVLvalues
+ \appendtoks\tabl_table_local_setups\to\everytable
+ \tabl_table_standard_begin[\ifsplittables u\else b\fi]%
+ \the\localtabledefinitions
+ \forgetall % added
+ \edef\currenttableformat{#1}%
+ \doifsomething\currenttableformat
+ {\dogettablenofcolumns\currenttableformat
+ % more modern is to use catcode tables
+ \expandafter\tabl_table_begin_format\currenttableformat\doendtableformat}}
+
+\def\tabl_table_finish
+ {\tabl_tables_chuck_auto_row
+ \unskip\crcr
+ \tabl_table_normal_end
+ \global\intablefalse
+ \egroup}
+
+%D \macros
+%D {starttables}
+%D
+%D Split tables are specified using the plural form of the start and stop commands.
+%D
+%D \showsetup{starttables}
+%D
+%D For example:
+%D
+%D \starttyping
+%D \starttables[|||]
+%D \HL
+%D \VL element \VL atom weight \VL\AR
+%D \HL
+%D \VL ....... \VL ........... \VL\AR
+%D \VL ....... \VL ........... \VL\AR
+%D \HL
+%D \stoptables
+%D \stoptyping
+
+\newbox\tablecontentbox
+
+\permanent\protected\def\starttables
+ {\bgroup
+ \enforced\let\stoptables\table_table_stop_s
+ \splittablestrue
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \ifx\p_tabl_table_split\v!repeat
+ \settrue\c_tabl_table_repeat_head
+ \settrue\c_tabl_table_repeat_tail
+ \else
+ \setfalse\c_tabl_table_repeat_head
+ \setfalse\c_tabl_table_repeat_tail
+ \fi
+ \flushnotes
+ \setbox\tablecontentbox\vbox\bgroup
+ \forgetall
+ \tabl_table_first_stage}
+
+\permanent\let\stoptables\relax % needed for \noalign
+
+\def\table_table_stop_s % not \protected as we need the lookahead (brrr)
+ {\tabl_tables_chuck_auto_row % AM: before the tail, else noalign problem
+ \ifconditional\c_tabl_table_repeat_tail\else\tabl_table_insert_tail\fi
+ \tabl_table_finish
+ \egroup
+ \dontcomplain
+ \tabl_table_split_box\tablecontentbox
+ \glet\tabl_table_head\empty % new here
+ \glet\tabl_table_tail\empty % new here
+ \flushnotes
+ \egroup}
+
+\def\tabl_table_split_box#1%
+ {\resettsplit
+ \def\tsplitminimumfreelines{2}%
+ \def\tsplitminimumfreespace{\zeropoint}%
+ \setbox\tsplitcontent\box#1%
+ \ifconditional\c_tabl_table_repeat_head \ifconditional\hassometablehead
+ \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplithead\vbox{\unvbox\tsplithead}% \vpack ?
+ \fi \fi
+ \ifconditional\c_tabl_table_repeat_tail \ifconditional\hassometabletail
+ \setbox\tsplittail\vsplit\tsplitcontent to \lineheight
+ \setbox\tsplittail\vbox{\unvbox\tsplittail}% \vpack ?
+ \fi \fi
+ \ifinsidefloat\else
+ \def\tsplitbeforeresult{\startbaselinecorrection}%
+ \def\tsplitafterresult {\stopbaselinecorrection}%
+ \fi
+ \handletsplit}
+
+%D When the table in the previous example is split across pages, only the first gets
+%D a head. We could have said something like:
+%D
+%D \starttyping
+%D \starttablehead
+%D \HL
+%D \VL element \VL atom weight \VL\AR
+%D \HL
+%D \stoptablehead
+%D
+%D \starttabletail
+%D \HL
+%D \stoptabletail
+%D
+%D \starttables[|||]
+%D \VL ....... \VL ........... \VL\AR
+%D \VL ....... \VL ........... \VL\AR
+%D \stoptables
+%D \stoptyping
+%D
+%D This time each split table gets a head line and ends with a rule. Keep in mind
+%D that such heads also apply to the unbroken ones and should be defined local
+%D (grouped) if needed. The rather complicated definition below is due to the fact
+%D that the stopcondition is interface language dependant.
+
+\let\tabl_table_head\empty % needs checking
+\let\tabl_table_tail\empty % needs checking
+
+\letvalue{\e!start\v!tablehead}\relax % todo: frozen, but we use a grabber
+\letvalue{\e!stop \v!tablehead}\relax % todo: frozen, but we use a grabber
+\letvalue{\e!start\v!tabletail}\relax % todo: frozen, but we use a grabber
+\letvalue{\e!stop \v!tabletail}\relax % todo: frozen, but we use a grabber
+
+%D The second argument is a dummy one, by scanning for it, we get rid of
+%D interfering spaces.
+
+\newconditional\preventtablebreak
+\newconditional\hassometablehead
+\newconditional\hassometabletail
+
+% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}}
+% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}}
+
+\permanent\protected\def\settablehead{\dodoubleempty\tabl_table_set_head} % todo: use pickup
+\permanent\protected\def\settabletail{\dodoubleempty\tabl_table_set_tail} % todo: use pickup
+
+\def\tabl_table_set_head[#1][#2]#3\end
+ {\gdef\tabl_table_head{\begincsname\??tablehead#1\endcsname}% new
+ \setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}}
+
+\def\tabl_table_set_tail[#1][#2]#3\end
+ {\gdef\tabl_table_tail{\begincsname\??tabletail#1\endcsname}% new
+ \setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}}
+
+\normalexpanded
+ {\def\csname\e!start\v!tablehead\endcsname#1\csname\e!stop\v!tablehead\endcsname%
+ {\settablehead#1\noexpand\end}}
+
+\normalexpanded
+ {\def\csname\e!start\v!tabletail\endcsname#1\csname\e!stop\v!tabletail\endcsname%
+ {\settabletail#1\noexpand\end}}
+
+%D Redundant \type{\HL}'s are removed automatically, so mid||lines can be used
+%D without problems.
+%D
+%D The order of the next macros is more or less random. First we implement error
+%D recovery. Errors are reported to the screen and log file as well as visualized in
+%D the table in teletype.
+
+\def\tabl_table_finish_row
+ {\crcr
+ \noalign\bgroup
+ \nobreak
+ \tabl_table_set_action\tableunknownstate
+ \glet\tabl_tables_check_auto_row\empty
+ \glet\tabl_tables_chuck_auto_row\empty
+ \global\currenttablecolumn\zerocount
+ \egroup}
+
+%D Next we enter the more complicated area of column and row switching. I won't go
+%D into much detail from now on, but just mention the general principles.
+%D
+%D \startitemize[3*ruim]
+%D \sym{\type{\SR}} end a separate row (between rules)
+%D \sym{\type{\FR}} end a first row (after a rule)
+%D \sym{\type{\MR}} end a mid row (between text lines)
+%D \sym{\type{\LR}} end a last row (before a rule)
+%D \stopitemize
+%D
+%D and best of all:
+%D
+%D \startitemize[continue]
+%D \sym{\type{\AR}} end a row with automatic spacing
+%D \stopitemize
+%D
+%D As far as possible, we report confusing situations. In most cases one can use
+%D \type{\AR}, which transfigurates itself into one of the other types.
+%D
+%D \starttyping
+%D \starttable[||]
+%D \HL
+%D \VL a separate row \VL\SR
+%D \HL
+%D \VL a first row \VL\FR
+%D \VL a mid row \VL\MR
+%D \VL a last row \VL\LR
+%D \HL
+%D \stoptable
+%D \stoptyping
+%D
+%D In this example we could have used \type{\AR} without problems.
+%D
+%D Color or gray scale backgrounds precede the content. They are passed over
+%D horizontal (division) lines when needed. Errors in the color template are traced
+%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\
+%D handles alignments, we cannot automate spacing for colored rows and columns.
+
+\tablerowzero\zerocount
+
+\appendtoks
+ \enforced\let\SR\tabl_table_SR
+ \enforced\let\FR\tabl_table_FR
+ \enforced\let\MR\tabl_table_MR
+ \enforced\let\LR\tabl_table_LR
+ \enforced\let\AR\tabl_table_AR
+\to \localtabledefinitions
+
+\protected\def\tabl_table_SR
+ {\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \orelse\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \orelse\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}%
+ \fi
+ \tabl_table_end_row_indeed\tableseparaterowstate\tablerowfactor\tablerowfactor}
+
+\protected\def\tabl_table_FR
+ {\ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}%
+ \orelse\ifnum\tableactionstate=\tablelastrowstate
+ \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}%
+ \fi
+ \tabl_table_end_row_indeed\tablefirstrowstate\tablerowfactor\tablerowzero}
+
+\protected\def\tabl_table_MR
+ {\ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{change \string\MR\space into \string\FR/\string\SR}%
+ \orelse\ifnum\tableactionstate=\tablelastrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\FR}%
+ \fi
+ \tabl_table_end_row_indeed\tablemidrowstate00}
+
+\protected\def\tabl_table_LR
+ {\ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{change \string\LR\space into \string\FR/\string\SR}%
+ \fi
+ \tabl_table_end_row_indeed\tablelastrowstate\tablerowzero\tablerowfactor}
+
+%D \macros
+%D {ifcheckTABLEcolums}
+%D
+%D The next macros handle the actual row ending. This macro also take care of space
+%D corrections due to table splitting when \type{\MR} and collegues are used. When
+%D tracing is enabled, the corrections as well as the values used to determine the
+%D available space are shown (in color). By default checking is off.
+
+\def\tabl_table_end_row_indeed#1#2#3%
+ {\tabl_table_set_action#1%
+ \ifcase#1\relax
+ % unknown
+ \or
+ \tabl_tables_end_line\SR\SR\tablerowfactor\tablerowfactor
+ \or
+ \tabl_tables_end_line\FR\FR\tablerowfactor\tablerowzero
+ \or
+ \ifnum\tableforcestate=\tableforcelastrowstate
+ \tabl_tables_end_line\MR\LR\tablerowzero\tablerowfactor
+ \orelse\ifnum\tableforcestate=\tableforcefirstrowstate
+ \tabl_tables_end_line\MR\FR\tablerowfactor\tablerowzero
+ \else
+ \tabl_tables_end_line\MR\MR\tablerowzero\tablerowzero
+ \fi
+ \or
+ \tabl_tables_end_line\LR\LR\tablerowzero\tablerowfactor
+ \fi
+ \noalign\bgroup
+ \tabl_table_set_force\tableunknownstate
+ \global\currenttablecolumn\zerocount
+ \ifconditional\preventtablebreak
+ \nobreak
+ \else
+ \goodbreak
+ \fi
+ \egroup}
+
+%D Handling \type{\AR} is postponed till the next row. The check takes care of
+%D the first and mid rows, the chuck macro |<|how about that name|>| handles
+%D the last row.
+
+\protected\def\tabl_table_AR
+ {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed
+ \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed}
+
+\let\tabl_tables_check_auto_row\empty
+\let\tabl_tables_chuck_auto_row\empty
+
+\def\tabl_tables_check_auto_row_indeed
+ {\glet\tabl_tables_check_auto_row\empty
+ \ifnum\tableactionstate=\tablerulestate \FR\orelse
+ \ifnum\tableactionstate=\tableunknownstate\FR\else
+ \MR\fi}
+
+\def\tabl_tables_chuck_auto_row_indeed
+ {\glet\tabl_tables_check_auto_row\empty
+ \glet\tabl_tables_chuck_auto_row\empty
+ \ifnum\tableactionstate=\tablerulestate \SR\orelse
+ \ifnum\tableactionstate=\tableunknownstate\SR\else
+ \LR\fi}
+
+%D When a table is split, we also add a tail and when present we repeat the table
+%D head. If a gets split indeed, the spacing before and after a horizontal rule is
+%D corrected according to what we expect.
+
+\def\tabl_tables_end_line#1#2#3#4%
+ {\ifx#1#2\else
+ \writestatus\m!TABLE{\string#1\space changed into \string#2}%
+ \fi
+ \expandafter\tabl_table_normal_line_format#3#4\crcr % \crcr nodig ?
+ \noalign{\nobreak\global\settrue\tableactionstatepermitted}}
+
+%D In order to prevent (as good as possible) alignment overflow and therefore \TEX\
+%D error messages, we check the maximum number of columns. We keep track of the
+%D current column and maximum column by means of two \COUNTERS. Keep in mind that
+%D the number of \type{|}'s and \type{\VL}'s or alike is always one more than the
+%D number of columns.
+
+\newcount\currenttablecolumn
+
+% DWhile defining this macro we change the \CATCODE\ of \type{|}. When counting the
+% Dbars, we use a non active representation of the bar, simply because we cannot be
+% Dsure if the bar is active or not.\footnote{Normally it is, but \TABLE\ changes
+% Dthe catcode when needed.}
+
+\bgroup
+ \catcode\barasciicode\othercatcode \permanent\gdef\tabl_table_bar{|}
+ \catcode\barasciicode\activecatcode\gdef\tabl_table_use_bar{\enforced\let|\tabl_table_bar}
+\egroup
+
+\bgroup \catcode\barasciicode\othercatcode
+
+\gdef\dogettablenofcolumns#1% todo: also divert this to lua as with tabulate
+ {\bgroup
+ \cleanupfeatures % needed !
+ \tabl_table_use_bar
+ \egroup}
+
+\egroup
+
+%D \startitemize[3*ruim]
+%D \sym{\type{\VL}} a vertical line
+%D \sym{\type{\VC}} a vertical colored line
+%D \sym{\type{\HL}} a horizontal line
+%D \sym{\type{\HC}} a horizontal colored line
+%D \stopitemize
+
+\newcount\c_tabl_table_vrule_thickness_factor
+\newcount\c_tabl_table_hrule_thickness_factor
+\newcount\c_tabl_table_drule_span
+
+\let\m_tabl_table_vrule_color\empty
+\let\m_tabl_table_hrule_color\empty
+
+\appendtoks
+ \enforced\let\VL\tabl_table_VL
+ \enforced\let\VC\tabl_table_VC
+ \enforced\let\HL\tabl_table_HL
+ \enforced\let\HC\tabl_table_HC
+ \enforced\let\VS\tabl_table_VS
+ \enforced\let\VD\tabl_table_VD
+ \enforced\let\VT\tabl_table_VT
+ \enforced\let\VN\tabl_table_VN
+\to \localtabledefinitions
+
+\def\tabl_table_resetVLvalues
+ {\global\currenttablecolumn\zerocount}
+
+\def\tabl_table_vrulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\global\c_tabl_table_vrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax}
+ {\xdef\m_tabl_table_vrule_color{#1}}}
+
+\permanent\tolerant\protected\def\tabl_table_VL[#1]%
+ {\tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn\plusone
+ \glet\m_tabl_table_vrule_color\empty
+ \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax
+ \iftok{#1}\emptytoks\else
+ \rawprocesscommalist[#1]\tabl_table_vrulecommand
+ \fi
+ \tabl_table_normal_line_complex_bar}% \relax breaks \use
+
+\permanent\let\tabl_table_VC\tabl_table_VL % for mojca
+
+% \starttable[|||]
+% \HL
+% \VL test \VS test \VL \FR
+% \VL test \VD test \VL \MR
+% \VL test \VT test \VL \LR
+% \HL
+% \stoptable
+
+\permanent\protected\def\tabl_table_VS {\VN1}
+\permanent\protected\def\tabl_table_VD {\VN2}
+\permanent\protected\def\tabl_table_VT {\VN3}
+\permanent\protected\def\tabl_table_VN#1{\global\c_tabl_table_n_of_vrules#1\relax\VL}
+
+\def\tabl_table_hrulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\global\c_tabl_table_hrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax}
+ {\xdef\m_tabl_table_hrule_color{#1}}}
+
+\permanent\tolerant\protected\def\tabl_table_HL[#1]%
+ {\tabl_tables_chuck_auto_row
+ \tabl_table_finish_row
+ \noalign\bgroup
+ \nobreak
+ \ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{skipping \string\HL}% \statusmessage
+ \else
+ \ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}%
+ \orelse\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\SR}%
+ \fi
+ \bgroup
+ \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
+ \iffirstargument
+ \glet\m_tabl_table_hrule_color\empty
+ \rawprocesscommalist[#1]\tabl_table_hrulecommand
+ \ifempty\m_tabl_table_hrule_color\else
+ \switchtocolor[\m_tabl_table_hrule_color]%
+ \fi
+ \fi
+ \tabl_table_normal_full_rule
+ \egroup
+ \tabl_table_account_width
+ \fi
+ \tabl_table_set_action\tablerulestate
+ \nobreak
+ \egroup}
+
+\aliased\let\tabl_table_HC\tabl_table_HL % for mojca
+
+%D \startitemize[3*ruim]
+%D \sym{\type{\NL}} a vertical skip
+%D \sym{\type{\NR}} goto the next row
+%D \sym{\type{\NC}} goto the next column
+%D \sym{\type{\FC}} a first column
+%D \sym{\type{\MC}} a mid column
+%D \sym{\type{\LC}} a last column
+%D \stopitemize
+
+% \starttable[|||]
+% \VL text \VL text \VL \AR
+% \TB[small]
+% \VL text \VL text \VL \AR
+% \TB[4*big]
+% \VL text \VL text \VL \AR
+% \stoptable
+
+% n+1 uitleggen
+
+\appendtoks
+ \enforced\let\TB\tabl_table_TB
+ \enforced\let\NL\tabl_table_NL % old
+ \enforced\let\NR\tabl_table_NR
+ \enforced\let\NC\tabl_table_NC
+ \enforced\let\FC\tabl_table_NC
+ \enforced\let\MC\tabl_table_NC
+ \enforced\let\LC\tabl_table_NC
+\to \localtabledefinitions
+
+\permanent\tolerant\protected\def\tabl_table_TB[#1]%
+ {\tabl_tables_chuck_auto_row
+ \tabl_table_finish_row
+ \noalign\bgroup
+ \blank[\iftok{#1}\emptytoks\c!NL\else#1\fi]%
+ \nobreak
+ \egroup}
+
+\aliased\let\tabl_table_NL\tabl_table_TB
+
+\protected\def\tabl_table_NR
+ {\global\currenttablecolumn\zerocount
+ \tabl_table_normal_line_ending
+ \noalign\bgroup
+ \nobreak
+ \tabl_table_set_action\tableunknownstate
+ \egroup}
+
+\protected\def\tabl_table_NC
+ {\tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_no_bar}
+
+%D \startitemize[3*broad]
+%D \sym{\type{\DL}}
+%D \sym{\type{\DV}} (\type{\VD})
+%D \sym{\type{\DC}}
+%D \sym{\type{\DR}}
+%D \stopitemize
+
+\newconditional\c_tabl_table_is_division
+
+\appendtoks
+ \global\setfalse\c_tabl_table_is_division
+ \enforced\let\DL\tabl_table_DL
+ \enforced\let\DC\tabl_table_DC
+ \enforced\let\DV\tabl_table_DV
+ \enforced\let\DR\tabl_table_DR
+\to \localtabledefinitions
+
+\def\tabl_table_check_division
+ {\ifconditional\c_tabl_table_is_division\else
+ \tabl_tables_chuck_auto_row
+ \global\currenttablecolumn\zerocount
+ \global\settrue\c_tabl_table_is_division
+ \fi}
+
+\def\tabl_table_drulecommand#1% global assignments
+ {\doifelsenumber{#1}
+ {\ifcase\c_tabl_table_drule_span
+ \global\c_tabl_table_drule_span#1\relax
+ \else
+ \global\c_tabl_table_hrule_thickness_factor#1\relax
+ \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_VLwidth\relax
+ \fi}
+ {\xdef\m_tabl_table_hrule_color{#1}}}
+
+\permanent\tolerant\protected\def\tabl_table_DL[#1]%
+ {\tabl_table_check_division
+ \ifnum\tableactionstate=\tablerulestate
+ \writestatus\m!TABLE{skipping \string\DL}%
+ \else
+ \ifnum\tableactionstate=\tablemidrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}%
+ \orelse\ifnum\tableactionstate=\tablefirstrowstate
+ \writestatus\m!TABLE{change \string\MR\space into \string\SR}%
+ \fi
+ \tabl_table_set_action\tableunknownstate
+ \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
+ \global\c_tabl_table_drule_span\zerocount
+ \iftok{#1}\emptytoks\else
+ \glet\m_tabl_table_hrule_color\empty
+ \rawprocesscommalist[#1]\tabl_table_drulecommand
+ % \ifempty\m_tabl_table_hrule_color\else
+ % \switchtocolor[\m_tabl_table_hrule_color]% see *DL*
+ % \fi
+ \fi
+ \ifcase\c_tabl_table_drule_span
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_single_rule
+ \or
+ \global\advance\currenttablecolumn \plustwo
+ \tabl_table_normal_single_rule
+ \else
+ \global\advance\currenttablecolumn \plusone
+ \tabl_table_normal_multi_rule
+ \fi
+ \fi}
+
+\permanent\protected\def\tabl_table_DV
+ {\tabl_table_DCV\tabl_table_normal_line_simple_bar}
+
+\permanent\protected\def\tabl_table_DC
+ {\tabl_table_DCV\tabl_table_normal_no_bar}
+
+\permanent\protected\def\tabl_table_DCV#1%
+ {\tabl_table_check_division
+ \tabl_tables_check_auto_row
+ \global\advance\currenttablecolumn \plusone
+ #1}
+
+\permanent\protected\def\tabl_table_DR
+ {\global\currenttablecolumn\zerocount % nog check
+ \tabl_table_normal_line_ending
+ \noalign\bgroup
+ \nobreak
+ \global\setfalse\c_tabl_table_is_division
+ \tabl_table_account_width % temporary solution
+ \tabl_table_set_action\tablerulestate
+ \egroup}
+
+\def\tabl_table_account_width
+ {\scratchdimen\d_tabl_table_line_thickness_unit}
+
+\permanent\def\tabl_table_TWO {\use\plustwo}
+\permanent\def\tabl_table_THREE{\use\plusthree}
+\permanent\def\tabl_table_FOUR {\use\plusfour}
+\permanent\def\tabl_table_FIVE {\use\plusfive}
+\permanent\def\tabl_table_SIX {\use\plussix}
+
+\appendtoks
+ \enforced\let\TWO \tabl_table_TWO
+ \enforced\let\THREE\tabl_table_THREE
+ \enforced\let\FOUR \tabl_table_FOUR
+ \enforced\let\FIVE \tabl_table_FIVE
+ \enforced\let\SIX \tabl_table_SIX
+ \enforced\let\SPAN \use
+ \enforced\let\REF \tabl_table_reformat
+\to \localtabledefinitions
+
+\installcorenamespace{tables}
+\installcorenamespace{tabledistance}
+\installcorenamespace{tablealign}
+
+\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables
+
+\setvalue{\??tabledistance\v!none }{\tabl_table_OpenUp00\def\LOW{\Lower6 }}
+\setvalue{\??tabledistance\v!small }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} % == baseline
+\setvalue{\??tabledistance\v!medium}{\tabl_table_OpenUp11\def\LOW{\Lower7 }}
+\setvalue{\??tabledistance\v!big }{\tabl_table_OpenUp22\def\LOW{\Lower8 }}
+
+\appendtoks
+ \expandnamespaceparameter\??tabledistance\directtablesparameter\c!distance\v!medium
+\to \localtabledefinitions
+
+\setvalue{\??tablealign\v!right }{\def\tabl_table_paralignment{\raggedright}}
+\setvalue{\??tablealign\v!left }{\def\tabl_table_paralignment{\raggedleft}}
+\setvalue{\??tablealign\v!middle }{\def\tabl_table_paralignment{\raggedcenter}}
+\setvalue{\??tablealign\s!unknown}{\def\tabl_table_paralignment{\notragged}}
+
+\appendtoks
+ \doifelse{\directtablesparameter\c!distance}\v!none
+ {\tablerowfactor\zerocount}
+ {\tablerowfactor\plustwo }%
+\to \localtabledefinitions
+
+\def\dohandlebar % here ?
+ {\ifmmode
+ \expandafter\domathmodebar
+ \orelse\ifintable
+ \expandafter\domathmodebar
+ \else
+ \expandafter\dotextmodebar
+ \fi}
+
+\appendtoks
+ \expandnamespaceparameter\??tablealign\directtablesparameter\c!align\s!unknown
+ \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246%
+ \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246%
+\to \everysetuptables
+
+\def\tabl_table_local_setups
+ {\directtablesparameter\c!commands\relax
+ \usebodyfontparameter\directtablesparameter
+ \d_tabl_table_line_thickness_unit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax
+ \edef\p_tabl_table_height{\directtablesparameter\c!height}%
+ \edef\p_tabl_table_depth{\directtablesparameter\c!depth}%
+ \ifx\p_tabl_table_height\v!strut
+ \let\tablestrutheightfactor\tablestrutheightfactor
+ \else
+ \let\tablestrutheightfactor\p_tabl_table_height
+ \fi
+ \ifx\p_tabl_table_depth\v!strut
+ \let\tablestrutdepthfactor\tablestrutdepthfactor
+ \else
+ \let\tablestrutdepthfactor\p_tabl_table_depth
+ \fi
+ \edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}%
+ \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}%
+ \d_tabl_table_strut_unit \dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont
+ \d_tabl_table_kern_unit .5em\relax
+ \s_tabl_table_inter_column_space_unit.5em plus 1fil minus .25em\relax
+ \d_tabl_table_column_width_unit \d_tabl_table_kern_unit
+ \d_tabl_table_kern_unit \d_tabl_table_kern_unit}
+
+%D As one can see, we didn't only add color, but also more control over spacing.
+%D
+%D \startbuffer[a]
+%D \starttable[|c|]
+%D \HL
+%D \VL \strut test \VL \FR
+%D \VL \strut test \VL \MR
+%D \VL \strut test \VL \MR
+%D \VL \strut test \VL \LR
+%D \HL
+%D \stoptable
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \starttabulate[|c|]
+%D \HL
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \NC test \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D In the next example, the first table is defined as:
+%D
+%D \typebuffer[a]
+%D
+%D and the second one as:
+%D
+%D \typebuffer[b]
+%D
+%D The first table is typeset using the default height and depth factors .8 and .4.
+%D The second table has both factors set to \type {strut}, and the third table shows
+%D what happens when we set the values to zero. The rightmost table is typeset using
+%D the tabulate environment.
+%D
+%D \startcombination[4*1]
+%D {$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=.8 d=.4}}
+%D {\setuptables[height=strut,depth=strut]$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=d=\type{strut}}}
+%D {\setuptables[height=0,depth=0]$\vcenter{\getbuffer[a]}$}
+%D {\hbox{h=d=0}}
+%D {$\vcenter{\getbuffer[b]}$}
+%D {\hbox{tabulate}}
+%D \stopcombination
+
+\setuptables
+ [\c!HL=\v!medium,
+ \c!VL=\v!medium,
+ \c!NL=\v!small,
+ \c!frame=,
+ \c!align=\v!right,
+ \c!depth=.40, % \v!strut
+ \c!height=.80, % \v!strut
+ \c!textwidth=,
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!distance=\v!medium,
+ \c!bodyfont=,
+ \c!commands=,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!split=\v!auto,
+ \c!openup=\zeropoint]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-tbl.lua b/tex/context/base/mkiv/tabl-tbl.lua
index 13d899de6..aa4d5051f 100644
--- a/tex/context/base/mkiv/tabl-tbl.lua
+++ b/tex/context/base/mkiv/tabl-tbl.lua
@@ -18,13 +18,16 @@ local commands = commands
local texsetcount = tex.setcount
-local separator = P("|")
-local nested = lpeg.patterns.nested
-local pattern = Ct((separator * (C(nested) + Cc("")) * C((1-separator)^0))^0)
+local separator = P("|") -- keep { }
+----- nested = C(lpeg.patterns.nested) -- remove { }
+local nested = lpeg.patterns.argument
+local pattern = Ct((separator * (nested + Cc("")) * C((1-separator)^0))^0)
local ctx_settabulatelastentry = context.settabulatelastentry
local ctx_settabulateentry = context.settabulateentry
+-- the lmtx raw processor handles {} like the normal one so we need to prune
+
local function presettabulate(preamble)
preamble = gsub(preamble,"~","d") -- let's get rid of ~ mess here
if find(preamble,"*",1,true) then
diff --git a/tex/context/base/mkiv/tabl-tbl.mkxl b/tex/context/base/mkiv/tabl-tbl.mkxl
index 4b2f31721..e9d45e0e8 100644
--- a/tex/context/base/mkiv/tabl-tbl.mkxl
+++ b/tex/context/base/mkiv/tabl-tbl.mkxl
@@ -231,8 +231,8 @@
\newtoks \everytabulatepar % where used ?
\newtoks \everytabulate % public ?
-\unexpanded\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
-\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
+\protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
+\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
@@ -297,22 +297,6 @@
% 1 = RC column raw RQ equal column raw
% 2 = HC column hook HQ equal column hook
-% handy helper (problem: we have an extra group when we nest; playing with en engine
-% solution turned out to be too messy due to states; an ignoreendgroup trick also is
-% messy and interferes).
-
-\def\tabulatenoalign % public ?
- {\noalign
- \bgroup
- \let\noalign\relax
- \let\tabulatenoalign\relax
- \let\next=}
-
-\def\starttabulatenoalign % public ?
- {\tabulatenoalign\bgroup}
-
-\let\stoptabulatenoalign\egroup
-
% [|lg{.}|] => \NG 12.34 \NC
\def\tabl_tabulate_nobreak_inject_tracer
@@ -334,22 +318,22 @@
\tabl_tabulate_break_no_tracer}
\def\tabl_tabulate_nobreak_inject
- {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}}
+ {\noalign{\tabl_tabulate_nobreak_inject_indeed}}
-\unexpanded\def\tabl_tabulate_hook_check
+\protected\def\tabl_tabulate_hook_check
{\ifnum\c_tabl_tabulate_type<\plustwo
\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
\else
\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
\fi}
-\unexpanded\def\tabl_tabulate_setups_check
+\protected\def\tabl_tabulate_setups_check
{\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname}
-\unexpanded\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook}
-\unexpanded\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi}
+\protected\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook}
+\protected\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi}
-\unexpanded\def\tabl_tabulate_shaped_par_begin
+\protected\def\tabl_tabulate_shaped_par_begin
{\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup}
\def\tabl_tabulate_shaped_par_finish
@@ -361,10 +345,10 @@
\ifdefined\dotagtabulatecell \else \let\dotagtabulatecell \relax \fi
\ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi
-\unexpanded\def\tabl_tabulate_check_local_color_first#1#2%
+\protected\def\tabl_tabulate_check_local_color_first#1#2%
{\relax}
-\unexpanded\def\tabl_tabulate_check_local_color_second#1#2%
+\protected\def\tabl_tabulate_check_local_color_second#1#2%
{\relax
\ifempty\m_tabl_tabulate_color_local
\xdef\m_tabl_tabulate_color{#1}%
@@ -379,7 +363,7 @@
\global\c_tabl_tabulate_localcolorspan\zerocount
\fi}
-\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1%
+\protected\def\tabl_tabulate_check_local_vrule_thickness#1%
{\relax
\ifcase\d_tabl_tabulate_vrulethickness_local
\global\d_tabl_tabulate_vrulethickness#1\relax
@@ -388,10 +372,10 @@
\global\d_tabl_tabulate_vrulethickness_local\zeropoint
\fi}
-\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1%
+\protected\def\tabl_tabulate_check_local_vrule_color_first#1%
{\relax}
-\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1%
+\protected\def\tabl_tabulate_check_local_vrule_color_second#1%
{\relax
\ifempty\m_tabl_tabulate_vrule_color_local
\xdef\m_tabl_tabulate_vrule_color{#1}%
@@ -413,7 +397,7 @@
\let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_second
\to \t_tabl_tabulate_initializers_second
-% \unexpanded % we can expand this one
+% \protected % we can expand this one
\def\tabl_tabulate_inject_pre_skip#1%
{\ifdim#1>\zeropoint
\kern#1\relax % was \hskip
@@ -425,7 +409,7 @@
\fi
\fi}
-% \unexpanded % we can expand this one
+% \protected % we can expand this one
\def\tabl_tabulate_inject_post_skip#1%
{\ifdim#1>\zeropoint
\kern#1\relax % was \hskip
@@ -531,7 +515,7 @@
%\let\gettabulateexit\dogettabulateexit % still needed ?
\d_tabl_tabulate_width\zeropoint}
-\unexpanded\def\installtabulatepreambleoption#1#2%
+\protected\def\installtabulatepreambleoption#1#2%
{\setvalue{\??tabulatepreamble\string#1}{#2}}%
\installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount
@@ -824,6 +808,7 @@
\global\d_tabl_tabulate_vrulethickness\zeropoint
\else
\global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ % the lmtx raw processor handles {} like the normal one so we need to prune
\rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
\fi
\tabl_tabulate_set_preamble#2\relax\relax % permits i without n
@@ -906,7 +891,7 @@
\tabl_tabulate_check_linenumbers
\box\b_tabl_tabulate}
-\unexpanded\def\tabl_tabulate_hook_nop
+\protected\def\tabl_tabulate_hook_nop
{}
\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
@@ -945,12 +930,12 @@
\fi}
\def\tabl_tabulate_pbreak_check
- {\starttabulatenoalign
+ {\noalign\bgroup
\tabl_tabulate_pbreak_inject
\ifconditional\c_tabl_tabulate_splitoff_whitespace
\tabl_tabulate_whitespace
\fi
- \stoptabulatenoalign}
+ \egroup}
%D \startbuffer
%D \starttabulate[|c|p|p|]
@@ -1040,44 +1025,42 @@
%\c!title=,
\c!indenting=\v!no]
-\unexpanded\def\definetabulate
- {\dotripleempty\tabl_tabulate_define}
-
-\def\tabl_tabulate_define[#1][#2][#3]%
- {\ifthirdargument
+\permanent\tolerant\protected\def\definetabulate[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ % ignore
+ \or
+ % [tag]
+ \definetabulation[#1][\c!format={|l|p|},\s!check=]%
+ \or
+ % [tag] [template]
+ \definetabulation[#1][\c!format={#2},\s!check=]%
+ \or
% [tag] [sub] [template]
\ifcsname\namedtabulationhash{#1}\s!check\endcsname \else
\definetabulation[#1][\c!format={#3},\s!check=]%
\fi
\definetabulation[#1:#2][#1][\c!format={#3},\s!check=]%
- \orelse\ifsecondargument
- % [tag] [template]
- \definetabulation[#1][\c!format={#2},\s!check=]%
- \else
- % [tag]
- \definetabulation[#1][\c!format={|l|p|},\s!check=]%
\fi}
-\unexpanded\def\setuptabulate
- {\dotripleempty\tabl_tabulate_setup}
-
-\def\tabl_tabulate_setup[#1][#2][#3]%
- {\ifthirdargument
- % [tag] [sub] [settings]
- \setuptabulation[#1:#2][#3]%
- \orelse\ifsecondargument
- % [tag] [settings]
- \setuptabulation[#1][#2]%
- \else
+\permanent\tolerant\protected\def\setuptabulate[#1]#*[#2]#*[#3]%
+ {\ifarguments
+ % ignore
+ \or
% [tag]
\setuptabulation[#1]%
+ \or
+ % [tag] [settings]
+ \setuptabulation[#1][#2]%
+ \or
+ % [tag] [sub] [settings]
+ \setuptabulation[#1:#2][#3]%
\fi}
\appendtoks
- \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}%
- \letvalue{\e!stop\currenttabulation}\relax
- \letvalue{\??tabulatehead\currenttabulation}\empty
- \letvalue{\??tabulatefoot\currenttabulation}\empty
+ \enforced\expandafter\edef\csname\e!start \currenttabulation\endcsname{\tabl_start_defined[\currenttabulation]}%
+ \enforced\expandafter\let \csname\e!stop \currenttabulation\endcsname\relax
+ \enforced\expandafter\let \csname\??tabulatehead\currenttabulation\endcsname\empty
+ \enforced\expandafter\let \csname\??tabulatefoot\currenttabulation\endcsname\empty
\to \everydefinetabulation
\let\tabulateparameter\tabulationparameter % will stay for a while
@@ -1090,14 +1073,14 @@
\let\tabl_tabulate_insert_foot\empty
\def\tabl_tabulate_insert_head_content
- {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ {\noalign{\global\settrue\c_tabl_tabulate_someamble}%
\begincsname\??tabulatehead\currenttabulation\endcsname
- \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+ \noalign{\global\setfalse\c_tabl_tabulate_someamble}}%
\def\tabl_tabulate_insert_foot_content
- {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ {\noalign{\global\settrue\c_tabl_tabulate_someamble}%
\begincsname\??tabulatefoot\currenttabulation\endcsname
- \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+ \noalign{\global\setfalse\c_tabl_tabulate_someamble}}%
\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
{\ifcsname\??tabulatehead\currenttabulation\endcsname
@@ -1124,7 +1107,7 @@
\def\tabl_tabulate_insert_content
{\tabl_tabulate_insert_head
\ifcase\c_tabl_tabulate_repeathead \else
- \tabulatenoalign{\penalty\zerocount}% added 7/5/2014 WS mail
+ \noalign{\penalty\zerocount}% added 7/5/2014 WS mail
\fi
\tabl_tabulate_insert_body
\tabl_tabulate_insert_foot
@@ -1133,7 +1116,7 @@
\def\tabl_tabulate_remove_funny_line
{\ifhmode
\strut\crcr
- \tabulatenoalign{\kern-\lineheight}%
+ \noalign{\kern-\lineheight}%
\fi}
% todo: make footer synonym to tail
@@ -1152,95 +1135,70 @@
\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[\v!tabulate]}
\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[\v!tabulate]}
-\unexpanded\def\tabl_start_defined[#1]%
+\protected\def\tabl_start_defined[#1]%
{\bgroup
\edef\currenttabulationparent{#1}%
\let\currenttabulation\currenttabulationparent
- \edef\p_format{\tabulationparameter\c!format}%
- \ifx\p_format\v!none
+ \iftok{\tabulationparameter\c!format}{\v!none}%
% this is special case: we need to define the generic english
% \starttabulate in other interfaces as well
- \expandafter\dodoubleempty \expandafter\tabl_start_regular
+ \lettabulationparameter\c!format\tabl_default_format
+ \expandafter\tabl_start_regular
\else
- \expandafter\dodoubleargument\expandafter\tabl_start_defined_indeed
+ \expandafter\tabl_start_defined_indeed
\fi}
-\def\tabl_start_defined_indeed
- {\iffirstargument
- \ifsecondargument
- \doubleexpandafter\tabl_start_defined_two
+\tolerant\def\tabl_start_defined_indeed[#1]#*[#2]%
+ {\ifarguments\or
+ \ifhastok={#1}%
+ \setuptabulation[\currenttabulation][#1]%
\else
- \doubleexpandafter\tabl_start_defined_one
+ \edef\currenttabulation{\currenttabulation:#1}%
\fi
\else
- \singleexpandafter\tabl_start_defined_zero
- \fi}
-
-\def\tabl_start_defined_one[#1][#2]%
- {\ifcondition\validassignment{#1}%
- \setuptabulation[\currenttabulation][#1]%
- \else
\edef\currenttabulation{\currenttabulation:#1}%
+ \setuptabulation[\currenttabulation][#2]%
\fi
\tabl_tabulate_start_building}
-\def\tabl_start_defined_two[#1][#2]%
- {\edef\currenttabulation{\currenttabulation:#1}%
- \setuptabulation[\currenttabulation][#2]%
- \tabl_tabulate_start_building}
-
-\def\tabl_start_defined_zero[#1][#2]%
- {\tabl_tabulate_start_building}
-
% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
-\unexpanded\setuvalue{\e!start\v!tabulate}%
+\def\tabl_default_format{|l|p|} % actually format is always set
+
+\permanent\protected\setuvalue{\e!start\v!tabulate}%
{\bgroup % whole thing
\let\currenttabulationparent\empty
- \dodoubleempty\tabl_start_regular}
+ \tabl_start_regular}
-\def\tabl_start_regular
+\tolerant\protected\def\tabl_start_regular[#1]#*[#2]% [format] | [settings] | [format] [settings] | [settings] [format]
{\let\currenttabulation\currenttabulationparent
- \ifsecondargument
- \expandafter\tabl_start_regular_two
- \else
- \expandafter\tabl_start_regular_one
- \fi}
-
-\def\tabl_default_format{|l|p|}
-
-\def\tabl_start_regular_one[#1][#2]%
- {\ifcondition\validassignment{#1}%
- \lettabulationparameter\c!format\tabl_default_format
+ \iftok{#1}\emptytoks
+ \ifhastok={#2}\relax
+ \setupcurrenttabulation[#2]%
+ \fi
+ \orelse\ifhastok={#1}
+ \ifhastok{#2}\relax
+ \settabulationparameter\c!format{#2}%
+ \fi
\setupcurrenttabulation[#1]%
\else
- \def\p_format{#1}%
- \ifempty\p_format
- \def\p_format{|l|p|}%
+ \settabulationparameter\c!format{#1}%
+ \ifhastok={#2}\relax
+ \setupcurrenttabulation[#2]%
\fi
- \lettabulationparameter\c!format\p_format
- \fi
- \tabl_tabulate_start_building}
-
-\def\tabl_start_regular_two[#1][#2]%
- {\def\p_format{#1}%
- \ifempty\p_format
- \let\p_format\tabl_default_format
\fi
- \lettabulationparameter\c!format\p_format
- \setupcurrenttabulation[#2]%
\tabl_tabulate_start_building}
\letvalue{\e!stop\v!tabulate }\relax
\letvalue{\e!stop\v!tabulatehead}\relax
\letvalue{\e!stop\v!tabulatetail}\relax
-\unexpanded\def\tabl_tabulate_start_ignore
+\permanent\protected\def\tabl_tabulate_start_ignore % todo when we go frozen
{\em Nested tabulate is not (yet) supported.\relax
\expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname}
\appendtoks
- \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
+ \enforced\letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
\to \everytabulate
\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split}
@@ -1283,7 +1241,7 @@
\let\tabl_tabulate_inside_inbetween \relax
\let\tabl_tabulate_outside_inbetween\relax
-\unexpanded\def\tabl_tabulate_inside_before
+\protected\def\tabl_tabulate_inside_before
{\ifhmode\par\fi
\ifhmode
\ifinsidesplitfloat
@@ -1296,7 +1254,7 @@
\let\tabl_tabulate_inside_after\relax
\fi}
-\unexpanded\def\tabl_tabulate_outside_before
+\protected\def\tabl_tabulate_outside_before
{\ifhmode\par\fi
\ifhmode
\vbox\bgroup
@@ -1328,7 +1286,7 @@
\verticalstrut
\vskip-\struttotal}}
-\unexpanded\def\tabl_tabulate_start_building
+\protected\def\tabl_tabulate_start_building
{\ifinsidefloat
\tabl_tabulate_inside_before
\else
@@ -1380,7 +1338,7 @@
\tabulationparameter\c!inner
\d_tabl_tabulate_indent\dimexpr\leftskip+\hangindent\ifx\p_indenting\v!yes+\parindent\fi\relax
\global\c_tabl_tabulate_column\zerocount
- \processcontent
+ \processcontent % stoptabulate needs to match the frozen one
{\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifempty\currenttabulationparent\v!tabulate\else\currenttabulationparent\fi\fi}
\tabl_tabulate_insert_body
\tabl_tabulate_process}
@@ -1422,13 +1380,13 @@
\global \d_tabl_tabulate_vrulethickness_local\zeropoint
\to \t_tabl_tabulate_every_row
-\unexpanded\def\tabl_tabulate_color_side_right_second
+\protected\def\tabl_tabulate_color_side_right_second
{\ifempty\m_tabl_tabulate_color_previous \else
\tabl_tabulate_color_set\m_tabl_tabulate_color_previous
\glet\m_tabl_tabulate_color_previous\empty
\fi}
-\unexpanded\def\tabl_tabulate_color_side_left_second
+\protected\def\tabl_tabulate_color_side_left_second
{\ifempty\m_tabl_tabulate_color \else
\ifcase\c_tabl_tabulate_colorspan
\or
@@ -1438,7 +1396,7 @@
\fi
\fi}
-\unexpanded\def\tabl_tabulate_color_side_both_second
+\protected\def\tabl_tabulate_color_side_both_second
{\ifempty\m_tabl_tabulate_color \else
\tabl_tabulate_color_set\m_tabl_tabulate_color
\ifcase\c_tabl_tabulate_colorspan
@@ -1462,7 +1420,7 @@
\let\tabl_tabulate_color_side_both \tabl_tabulate_color_side_both_second
\to \t_tabl_tabulate_initializers_second
-\def\tabl_tabulate_set_color_column#1% overloaded
+\def\tabl_tabulate_set_color_column#1% overloaded / todo
{\unskip
\doifelsefastoptionalcheck{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}}
@@ -1566,13 +1524,13 @@
{\dousecolorparameter\m_tabl_tabulate_vrule_color
\vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
-\unexpanded\def\tabl_tabulate_column_vrule_inject_first
+\protected\def\tabl_tabulate_column_vrule_inject_first
{\ifcase\d_tabl_tabulate_vrulethickness\else
\tabl_tabulate_column_vruled_normal % could be a skip instead
\fi
\global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
-\unexpanded\def\tabl_tabulate_column_vrule_inject_second
+\protected\def\tabl_tabulate_column_vrule_inject_second
{\ifcase\d_tabl_tabulate_vrulethickness\else
\ifempty\m_tabl_tabulate_vrule_color
\tabl_tabulate_column_vruled_normal
@@ -1602,9 +1560,9 @@
\expandafter\ignorespaces % interferes with the more tricky hooks
\fi}
-\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
- {\let#1\tabl_tabulate_column_inject_auto
- \let\\\tabl_tabulate_column_inject_auto} % brrr, will go
+\protected\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
+ {\enforced\let#1\tabl_tabulate_column_inject_auto
+ \enforced\let\\\tabl_tabulate_column_inject_auto} % brrr, will go
\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
@@ -1636,24 +1594,15 @@
\directvskip\s_tabl_tabulate_separator
\egroup}
-\def\tabl_tabulate_hrule_spec_ignore#1%
- {%\glet\currenttabulationlocalhrulecolor\empty
- %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
- \doifelsefastoptionalcheck#1#1}
-
-\def\tabl_tabulate_hrule_spec_pickup#1%
- {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
- \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
- \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
-
\def\tabl_tabulate_hrule_preset_step#1%
{\doifelsenumber{#1}
{\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
{\xdef\currenttabulationlocalhrulecolor{#1}}}
-\def\tabl_tabulate_hrule_preset#1[#2]%
- {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
- #1}
+\def\tabl_tabulate_hrule_preset[#1]%
+ {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
+ \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
+ \iftok{#1}\emptytoks\else\rawprocesscommalist[#1]\tabl_tabulate_hrule_preset_step\fi}
\def\tabl_tabulate_hrule_inject_normal
{\autorule
@@ -1666,12 +1615,12 @@
{\dousecolorparameter\currenttabulationlocalhrulecolor
\tabl_tabulate_hrule_inject_normal}
-\unexpanded\def\tabl_tabulate_hrule_inject_first
+\protected\def\tabl_tabulate_hrule_inject_first
{\ifcase\d_tabl_tabulate_hrulethickness_local\else
\tabl_tabulate_hrule_inject_normal
\fi}
-\unexpanded\def\tabl_tabulate_hrule_inject_second
+\protected\def\tabl_tabulate_hrule_inject_second
{\ifcase\d_tabl_tabulate_hrulethickness_local\else
\ifempty\currenttabulationlocalhrulecolor
\tabl_tabulate_hrule_inject_normal
@@ -1715,7 +1664,7 @@
% \NC test \CC[yellow] test \NC test \NC \NR
% \stoptabulate
-\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
+\protected\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
{\begingroup
\clf_enablebackgroundalign % was \node_backgrounds_align_initialize
\glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
@@ -1821,7 +1770,7 @@
\def\tabl_tabulate_digits{\digits}
-%D Beware, we cannot use \type {\unexpanded} on \type {\HL} cum suis, since \TEX's
+%D Beware, we cannot use \type {\protected} on \type {\HL} cum suis, since \TEX's
%D hard coded noalign lookahead fails on it! I mistakenly added this for a while.
\setvalue{\??tabulatealigning\v!normal}{0}
@@ -1832,10 +1781,10 @@
\setvalue{\??tabulateheader\v!repeat}{\plusone}
\setvalue{\??tabulateheader\v!text }{\plustwo}
-\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
-\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
-\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
-\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+\protected\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\protected\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
+\protected\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\protected\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
\let\tabl_tabulate_bbskip\relax
\let\tabl_tabulate_eeskip\relax
@@ -1873,28 +1822,28 @@
% so far
-\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount}
-\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount}
-\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone}
-\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo}
-\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount}
-\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone}
-\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo}
+\permanent\protected\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount}
+\permanent\protected\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount}
+\permanent\protected\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone}
+\permanent\protected\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo}
+\permanent\protected\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount}
+\permanent\protected\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone}
+\permanent\protected\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo}
-\unexpanded\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount}
-\unexpanded\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first
-\unexpanded\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake
+\permanent\protected\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount}
+\permanent\protected\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first
+\permanent\protected\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake
-\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
-\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
+\permanent\protected\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
+\permanent\protected\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
-\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
-\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
+\permanent\protected\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
+\permanent\protected\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
-\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
-\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount}
-\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount}
-\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
+\permanent\protected\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
+\permanent\protected\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount}
+\permanent\protected\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount}
+\permanent\protected\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
%D Sort of special:
%D
@@ -1920,53 +1869,50 @@
%D
%D \typebuffer \getbuffer
-\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop}
-
-\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC}
-\def\tabl_tbl_NI_nop {\NC \itemtag \NC}
+\permanent\tolerant\protected\def\tabl_tabulate_NI_first[#1]{\NC\itemtag[#1]\NC}
%D The following shortcut is handy for tables where one needs bold headers:
-\unexpanded\def\tabl_tabulate_BC_first
+\permanent\protected\def\tabl_tabulate_BC_first
{\tabl_tabulate_column_normal\plusone\zerocount
\let\fontstyle\globalfontstyle
\bf}
\appendtoks
- \let\VL\tabl_tabulate_VL_first
- \let\NC\tabl_tabulate_NC_first
- \let\BC\tabl_tabulate_BC_first
- \let\RC\tabl_tabulate_RC_first
- \let\HC\tabl_tabulate_HC_first
- \let\EQ\tabl_tabulate_EQ_first
- \let\RQ\tabl_tabulate_RQ_first
- \let\HQ\tabl_tabulate_HQ_first
- \let\NG\tabl_tabulate_NG_first
- \let\NN\tabl_tabulate_NN_first
- \let\ND\tabl_tabulate_ND_first
- \let\NR\tabl_tabulate_NR_first
- \let\NB\tabl_tabulate_NB_first
- \let\CC\tabl_tabulate_CC_first
- \let\CL\tabl_tabulate_CL_first
- \let\CM\tabl_tabulate_CM_first
- \let\CR\tabl_tabulate_CR_first
- \let\NI\tabl_tabulate_NI_first
+ \enforced\let\VL\tabl_tabulate_VL_first
+ \enforced\let\NC\tabl_tabulate_NC_first
+ \enforced\let\BC\tabl_tabulate_BC_first
+ \enforced\let\RC\tabl_tabulate_RC_first
+ \enforced\let\HC\tabl_tabulate_HC_first
+ \enforced\let\EQ\tabl_tabulate_EQ_first
+ \enforced\let\RQ\tabl_tabulate_RQ_first
+ \enforced\let\HQ\tabl_tabulate_HQ_first
+ \enforced\let\NG\tabl_tabulate_NG_first
+ \enforced\let\NN\tabl_tabulate_NN_first
+ \enforced\let\ND\tabl_tabulate_ND_first
+ \enforced\let\NR\tabl_tabulate_NR_first
+ \enforced\let\NB\tabl_tabulate_NB_first
+ \enforced\let\CC\tabl_tabulate_CC_first
+ \enforced\let\CL\tabl_tabulate_CL_first
+ \enforced\let\CM\tabl_tabulate_CM_first
+ \enforced\let\CR\tabl_tabulate_CR_first
+ \enforced\let\NI\tabl_tabulate_NI_first
\to \t_tabl_tabulate_initializers_first
\appendtoks
- \let\NR\tabl_tabulate_NR_second
- \let\NB\tabl_tabulate_NB_second
+ \enforced\let\NR\tabl_tabulate_NR_second
+ \enforced\let\NB\tabl_tabulate_NB_second
\to \t_tabl_tabulate_initializers_second
\appendtoks
- \let\SR\NR
- \let\FR\NR
- \let\MR\NR
- \let\LR\NR
- \let\AR\NR
+ \enforced\let\SR\NR
+ \enforced\let\FR\NR
+ \enforced\let\MR\NR
+ \enforced\let\LR\NR
+ \enforced\let\AR\NR
\to \t_tabl_tabulate_initializers_first
-\unexpanded\def\tabl_tabulate_NR_common#1#2%
+\permanent\protected\def\tabl_tabulate_NR_common#1#2%
{\global\advance\c_tabl_tabulate_noflines\plusone
\global\setfalse\c_tabl_tabulate_firstflushed
\global\setfalse\c_tabl_tabulate_equal
@@ -1977,10 +1923,7 @@
\tabl_tabulate_pheight_reset
\unskip\unskip\crcr\tabl_tabulate_flush_collected
% can we omit the next one in the first run? probably
- \starttabulatenoalign
- \the\t_tabl_tabulate_every_after_row
- #2%
- \stoptabulatenoalign}
+ \noalign{\the\t_tabl_tabulate_every_after_row#2}}
\def\tabl_tabulate_check_penalties
{\ifconditional\c_tabl_tabulate_tolerant_break\else
@@ -2005,20 +1948,20 @@
\fi
\global\setfalse\c_tabl_tabulate_firstflushed}
-\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
+\protected\def\tabl_tabulate_bbskip_second_split_yes
{\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
\ifempty\tabl_tabulate_flush_collected_indeed\else
\setbox0\hbox
\fi
\fi}
-\unexpanded\def\tabl_tabulate_eskip_second
+\protected\def\tabl_tabulate_eskip_second
{\par\egroup
\tabl_tabulate_pheight_set
\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
\tabl_tabulate_splitoff_box}
-\unexpanded\def\tabl_tabulate_bskip_second_split_yes
+\protected\def\tabl_tabulate_bskip_second_split_yes
{\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
% first line
\global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
@@ -2037,33 +1980,33 @@
\expandafter\tabl_tabulate_splitoff_box
\fi}
-\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
-\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
+\protected\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
+\protected\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
-\unexpanded\def\tabl_tabulate_flush_second_indeed
+\protected\def\tabl_tabulate_flush_second_indeed
{\glet\tabl_tabulate_flush_collected_indeed\empty
\global\c_tabl_tabulate_column\zerocount
\tabl_tabulate_pbreak_check
\dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
\global\settrue\c_tabl_tabulate_firstflushed}
-\unexpanded\def\tabl_tabulate_flush_second_step
+\protected\def\tabl_tabulate_flush_second_step
{\ifvoid\b_tabl_tabulate_current\fastloopindex\else
\gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
\fi}
\def\tabl_tabulate_flush_second
- {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
+ {\noalign{\tabl_tabulate_flush_second_indeed}%
\tabl_tabulate_flush_collected_indeed}
-\unexpanded\def\tabl_tabulate_bskip_second_split_nop
+\protected\def\tabl_tabulate_bskip_second_split_nop
{\vtop\bgroup
\ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
% \begstrut % interferes with pre-\pars
% evt: \appendtoks\begstrut\to\everypar
\ignorespaces}
-\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
+\protected\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
{\par\verticalstrut
\vskip-\struttotal
\egroup}
@@ -2090,19 +2033,15 @@
% \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
% \stoptext
-\def\tabl_tabulate_XX_none
- {\starttabulatenoalign
- \tabl_tabulate_break_state_set
- \tabl_tabulate_hrule_spec_ignore
- \stoptabulatenoalign}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_XX_none [#1]{\noalign{\tabl_tabulate_break_state_set}}
-\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
-\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
-\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
-\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
-\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_FL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_FL_second_indeed}}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_ML_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_ML_second_indeed}}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_LL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_LL_second_indeed}}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_TL_second_indeed}}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_BL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_BL_second_indeed}}
-\unexpanded\def\tabl_tabulate_FL_second_indeed
+\protected\def\tabl_tabulate_FL_second_indeed
{\ifinsidefloat\else
\doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
\fi
@@ -2110,13 +2049,12 @@
\tabl_tabulate_nobreak_inject
\tabl_tabulate_column_rule_separator_inject
\prevdepth\strutdp
- \tabl_tabulate_nobreak_inject
- \stoptabulatenoalign}
+ \tabl_tabulate_nobreak_inject}
\def\spac_vspacing_no_topskip % use grouped
{\c_attr_skipcategory\plusten}
-\unexpanded\def\tabl_tabulate_ML_second_indeed
+\protected\def\tabl_tabulate_ML_second_indeed
{\tabl_tabulate_break_no
\tabl_tabulate_column_rule_separator_inject
\tabl_tabulate_break_no
@@ -2127,10 +2065,9 @@
\tabl_tabulate_hrule_inject
\endgroup
\tabl_tabulate_break_no
- \tabl_tabulate_column_rule_separator_inject
- \stoptabulatenoalign}
+ \tabl_tabulate_column_rule_separator_inject}
-\unexpanded\def\tabl_tabulate_LL_second_indeed
+\protected\def\tabl_tabulate_LL_second_indeed
{\tabl_tabulate_nobreak_inject
\tabl_tabulate_column_rule_separator_inject
\tabl_tabulate_nobreak_inject
@@ -2139,10 +2076,9 @@
\tabl_tabulate_inside_inbetween
\else
\tabl_tabulate_outside_inbetween
- \fi
- \stoptabulatenoalign}
+ \fi}
-\unexpanded\def\tabl_tabulate_TL_second_indeed
+\protected\def\tabl_tabulate_TL_second_indeed
{\tabl_tabulate_nobreak_inject
\tabl_tabulate_column_rule_separator_inject
\tabl_tabulate_nobreak_inject
@@ -2150,12 +2086,11 @@
\tabl_tabulate_nobreak_inject
\tabl_tabulate_column_rule_separator_inject
%\prevdepth\strutdp % todo, might differ between TL and BL
- \tabl_tabulate_nobreak_inject
- \stoptabulatenoalign}
+ \tabl_tabulate_nobreak_inject}
\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
-\def\tabl_tabulate_HL_second
+\permanent\def\tabl_tabulate_HL_second
{\csname
\ifnum\c_tabl_tabulate_noflines=\zerocount F\orelse
\ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
@@ -2163,52 +2098,25 @@
L\endcsname}
\appendtoks
- \let\FL\tabl_tabulate_XX_none
- \let\ML\tabl_tabulate_XX_none
- \let\LL\tabl_tabulate_XX_none
- \let\TL\tabl_tabulate_XX_none
- \let\BL\tabl_tabulate_XX_none
- \let\HL\tabl_tabulate_XX_none
- \let\HR\tabl_tabulate_XX_none
+ \enforced\let\FL\tabl_tabulate_XX_none
+ \enforced\let\ML\tabl_tabulate_XX_none
+ \enforced\let\LL\tabl_tabulate_XX_none
+ \enforced\let\TL\tabl_tabulate_XX_none
+ \enforced\let\BL\tabl_tabulate_XX_none
+ \enforced\let\HL\tabl_tabulate_XX_none
+ \enforced\let\HR\tabl_tabulate_XX_none
\to \t_tabl_tabulate_initializers_first
\appendtoks
- \let\FL\tabl_tabulate_FL_second
- \let\ML\tabl_tabulate_ML_second
- \let\LL\tabl_tabulate_LL_second
- \let\TL\tabl_tabulate_TL_second
- \let\BL\tabl_tabulate_BL_second
- \let\HL\tabl_tabulate_HL_second
- \let\HR\tabl_tabulate_HL_second
+ \enforced\let\FL\tabl_tabulate_FL_second
+ \enforced\let\ML\tabl_tabulate_ML_second
+ \enforced\let\LL\tabl_tabulate_LL_second
+ \enforced\let\TL\tabl_tabulate_TL_second
+ \enforced\let\BL\tabl_tabulate_BL_second
+ \enforced\let\HL\tabl_tabulate_HL_second
+ \enforced\let\HR\tabl_tabulate_HL_second
\to \t_tabl_tabulate_initializers_second
-% \def\tabulatedoHRfive % horizontal rule line (break untested)
-% {\starttabulatenoalign
-% \glet\dotabulateautoline\dotabulatelinerule
-% %\ifcase#1\or % todo: check what this does
-% \ifnum\noftabulatelines=\zerocount
-% \glet\dotabulateautoline\donothing
-% \orelse\ifnum\noftabulatelines=\totalnoftabulatelines
-% \glet\dotabulateautoline\donothing
-% \fi
-% %\fi
-% \dotabulatenobreak
-% \stoptabulatenoalign
-% \dotabulateautoline
-% \starttabulatenoalign
-% \tabl_tabulate_break_no
-% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
-% \ifnum\noftabulatelines=\totalnoftabulatelines
-% \expandafter\dotabulatenobreak
-% \else
-% \expandafter\tabl_tabulate_break_allow
-% \fi
-% \stoptabulatenoalign
-% \dotabulateautoline
-% \starttabulatenoalign
-% \dotabulatenobreak
-% \stoptabulatenoalign}
-
% \dorecurse{10}{
% \starttabulate[|l|]
% \FL
@@ -2393,7 +2301,7 @@
\the\t_tabl_tabulate_initializers_second % collect more here
%
\ifx\p_line\v!line
- \let\HL\HR
+ \enforced\let\HL\HR
\let\tabulateautoline\tabulateautorule
\let\tabulateline\tabulaterule
\fi
@@ -2505,36 +2413,19 @@
% \NC text \NC text \NC \NR
% \stoptabulate
-\def\tabl_tabulate_TB
- {\starttabulatenoalign
- \dosingleempty\tabl_tabulate_TB_indeed}
-
-\def\tabl_tabulate_TB_indeed[#1]%
- {\iffirstargument
- \blank[#1]
- \orelse\ifempty\m_tabl_tabulate_blank_default
- \blank
- \else
- \blank[\m_tabl_tabulate_blank_default]%
- \fi
- \stoptabulatenoalign}
-
-% to be tested:
-%
-% \def\tabl_tabulate_TB
-% {\starttabulatenoalign
-% \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
-%
-% \def\tabl_tabulate_TB_yes[#1]%
-% {\blank[#1]
-% \stoptabulatenoalign}
-%
-% \def\tabl_tabulate_TB_nop[#1]%
-% {\blank
-% \stoptabulatenoalign}
+\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TB[#1]%
+ {\noalign\bgroup
+ \unless\iftok{#1}\emptytoks
+ \blank[#1]
+ \orelse\ifempty\m_tabl_tabulate_blank_default
+ \blank
+ \else
+ \blank[\m_tabl_tabulate_blank_default]%
+ \fi
+ \egroup}
\appendtoks
- \let\TB\tabl_tabulate_TB
+ \enforced\let\TB\tabl_tabulate_TB
\to \everytabulate
% %D Between alignment lines certain rules apply, and even a simple test can mess
@@ -2701,13 +2592,17 @@
\newconditional\c_tabl_generic
-\unexpanded\setuvalue{starttabulate}%
+\pushoverloadmode
+
+\permanent\protected\setuvalue{starttabulate}%
{\bgroup % whole thing
\settrue\c_tabl_generic
\let\currenttabulationparent\empty
- \dodoubleempty\tabl_start_regular}
+ \tabl_start_regular}
-\letvalue{stoptabulate}\relax
+\permanent\letvalue{stoptabulate}\relax % testcase cvs-002.tex
+
+\popoverloadmode
%D The following helpers are just there because we also have them at the \LUA\ end:
%D
@@ -2734,10 +2629,10 @@
\expandafter\tabl_tabulate_compact_step
\fi#1}
-\unexpanded\def\tabulaterow {\tabl_tabulate_compact_row\relax}
-\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
-\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
-\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
+\permanent\protected\def\tabulaterow {\tabl_tabulate_compact_row\relax}
+\permanent\protected\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
+\permanent\protected\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
+\permanent\protected\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
%D Here we plug in a row background feature. As we only have support for
%D \type {frame=name} we can use these variables.
@@ -2823,13 +2718,13 @@
\let\m_table_current_row_background_defaultfiller\empty
\let\m_table_current_row_background_auto \empty
-\unexpanded\def\tabl_register_row_background#1%
+\protected\def\tabl_register_row_background#1%
{\xdef\m_table_current_row_background{#1}}
-\unexpanded\def\tabl_register_row_background_filler#1%
+\protected\def\tabl_register_row_background_filler#1%
{\xdef\m_table_current_row_background_filler{#1}}
-\unexpanded\def\tabl_synchronize_row_background
+\protected\def\tabl_synchronize_row_background
{\iftrialtypesetting\else
\ifempty\m_table_current_row_background_filler
\ifempty\m_table_current_row_background
@@ -2843,7 +2738,7 @@
\fi
\fi}
-\unexpanded\def\tabl_synchronize_row_background_dummy
+\protected\def\tabl_synchronize_row_background_dummy
{\iftrialtypesetting\else
\begingroup
%\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
@@ -2851,7 +2746,7 @@
\endgroup
\fi}
-\unexpanded\def\tabl_synchronize_row_background_indeed#1%
+\protected\def\tabl_synchronize_row_background_indeed#1%
{\iftrialtypesetting\else
\begingroup
\clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
@@ -2862,7 +2757,7 @@
\endgroup
\fi}
-\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
+\protected\def\tabl_synchronize_row_background_filler_indeed#1%
{\iftrialtypesetting\else
\begingroup
\clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
@@ -2898,21 +2793,27 @@
\glet\m_table_current_row_background_filler\empty
\to \t_tabl_tabulate_every_after_row
-\unexpanded\def\tabl_tabulate_NL_first[#1]%
+\permanent\protected\def\tabl_tabulate_NL_first[#1]%
{\tabl_tabulate_column_normal\zerocount\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background{#1}%
\fi
\ignorespaces}
-\unexpanded\def\tabl_tabulate_ND_first
- {\tabl_tabulate_column_normal\zerocount\zerocount\relax
- \ifcase\c_tabl_tabulate_column\or
- \tabl_register_row_background\m_table_current_row_background_default
- \fi
- \ignorespaces}
+\pushoverloadmode
+
+ % redefinition needs checking
-\unexpanded\def\tabl_tabulate_LB_first[#1]%
+ \permanent\overloaded\protected\def\tabl_tabulate_ND_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background\m_table_current_row_background_default
+ \fi
+ \ignorespaces}
+
+\popoverloadmode
+
+\permanent\protected\def\tabl_tabulate_LB_first[#1]%
{\tabl_tabulate_column_normal\plusone\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background{#1}%
@@ -2920,30 +2821,30 @@
\usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
\ignorespaces}
-\unexpanded\def\tabl_tabulate_DB_first
+\permanent\protected\def\tabl_tabulate_DB_first
{\tabl_tabulate_column_normal\plusone\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background\m_table_current_row_background_default
\fi
- \let\fontstyle\globalfontstyle
+ \enforced\let\fontstyle\globalfontstyle
\usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
\ignorespaces}
-\unexpanded\def\tabl_tabulate_NF_first[#1]%
+\permanent\protected\def\tabl_tabulate_NF_first[#1]%
{\tabl_tabulate_column_normal\zerocount\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background_filler{#1}%
\fi
\ignorespaces}
-\unexpanded\def\tabl_tabulate_NP_first
+\permanent\protected\def\tabl_tabulate_NP_first
{\tabl_tabulate_column_normal\zerocount\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background_filler\m_table_current_row_background_default_filler
\fi
\ignorespaces}
-\unexpanded\def\tabl_tabulate_FB_first[#1]%
+\permanent\protected\def\tabl_tabulate_FB_first[#1]%
{\tabl_tabulate_column_normal\plusone\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background_filler{#1}%
@@ -2951,29 +2852,33 @@
\usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
\ignorespaces}
-\unexpanded\def\tabl_tabulate_PB_first
+\permanent\protected\def\tabl_tabulate_PB_first
{\tabl_tabulate_column_normal\plusone\zerocount\relax
\ifcase\c_tabl_tabulate_column\or
\tabl_register_row_background_filler\m_table_current_row_background_default_filler
\fi
- \let\fontstyle\globalfontstyle
+ \enforced\let\fontstyle\globalfontstyle
\usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
\ignorespaces}
-\unexpanded\def\tabl_tabulate_BC_first % overloaded
- {\tabl_tabulate_column_normal\plusone\zerocount
- \let\fontstyle\globalfontstyle
- \ifempty\m_table_current_row_background
- \ifempty\m_table_current_row_background_filler
- \usetabulationstyleandcolor\c!headstyle\c!headcolor
- \else
- \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
- \fi
- \else
- \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
- \fi}
+\pushoverloadmode
+
+ \permanent\overloaded\protected\def\tabl_tabulate_BC_first
+ {\tabl_tabulate_column_normal\plusone\zerocount
+ \enforced\let\fontstyle\globalfontstyle
+ \ifempty\m_table_current_row_background
+ \ifempty\m_table_current_row_background_filler
+ \usetabulationstyleandcolor\c!headstyle\c!headcolor
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi}
+
+\popoverloadmode
-\unexpanded\def\tabl_tabulate_A_first
+\permanent\protected\def\tabl_tabulate_A_first
{\global\advance\c_tabl_tabulate_autocolor\plusone
\edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
\ifempty\m_table_current_row_background_auto
@@ -2985,7 +2890,7 @@
\fi
\tabl_register_row_background{\m_table_current_row_background_auto}}
-\unexpanded\def\tabl_tabulate_NA_first
+\permanent\protected\def\tabl_tabulate_NA_first
{\tabl_tabulate_column_normal\zerocount\zerocount\relax
\iftrialtypesetting\else
\ifcase\c_tabl_tabulate_column\or
@@ -2994,7 +2899,7 @@
\fi
\ignorespaces}
-\unexpanded\def\tabl_tabulate_BA_first
+\permanent\protected\def\tabl_tabulate_BA_first
{\tabl_tabulate_column_normal\plusone\zerocount\relax
\iftrialtypesetting\else
\ifcase\c_tabl_tabulate_column\or
@@ -3005,16 +2910,16 @@
\ignorespaces}
\appendtoks
- \let\NL\tabl_tabulate_NL_first % NC with Line
- \let\ND\tabl_tabulate_ND_first % NC with Default Line
- \let\LB\tabl_tabulate_LB_first % BC with Line
- \let\DB\tabl_tabulate_DB_first % BC with Default Line
- \let\NF\tabl_tabulate_NF_first % NC with Filler
- \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
- \let\FB\tabl_tabulate_FB_first % BC with Filler
- \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
- \let\NA\tabl_tabulate_NA_first % NC with Auto Line
- \let\BA\tabl_tabulate_BA_first % NC with Auto Line
+ \enforced\let\NL\tabl_tabulate_NL_first % NC with Line
+ \enforced\let\ND\tabl_tabulate_ND_first % NC with Default Line
+ \enforced\let\LB\tabl_tabulate_LB_first % BC with Line
+ \enforced\let\DB\tabl_tabulate_DB_first % BC with Default Line
+ \enforced\let\NF\tabl_tabulate_NF_first % NC with Filler
+ \enforced\let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
+ \enforced\let\FB\tabl_tabulate_FB_first % BC with Filler
+ \enforced\let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
+ \enforced\let\NA\tabl_tabulate_NA_first % NC with Auto Line
+ \enforced\let\BA\tabl_tabulate_BA_first % NC with Auto Line
\to \t_tabl_tabulate_initializers_first
\appendtoks
diff --git a/tex/context/base/mkiv/tabl-xnt.mklx b/tex/context/base/mkiv/tabl-xnt.mklx
new file mode 100644
index 000000000..f2a41c500
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-xnt.mklx
@@ -0,0 +1,142 @@
+% macros=mkvi
+
+%D \module
+%D [ file=tabl-xtb,
+%D version=2011.10.28,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Natural to Xtreme Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Natural to Xtreme Tables}
+
+\unprotect
+
+%D Don't expect wonders but it might come in handy:
+%D
+%D \starttyping
+%D \mapTABLEtoxtable
+%D \restoreTABLEfromxtable
+%D \stoptyping
+%D
+%D We stick to a simple example:
+%D
+%D \startbuffer
+%D \bTABLE
+%D \bTR
+%D \bTD[width=1cm,background=color,backgroundcolor=red] one \eTD
+%D \bTD[width=2cm] two \eTD
+%D \eTR
+%D \bTR
+%D \bTD alpha \eTD
+%D \bTD beta \eTD
+%D \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startbuffer
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \mapTABLEtoxtable \getbuffer
+%D \stoplinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\pushoverloadmode % this file is runtime loaded
+
+\overloaded\permanent\let\tabl_x_normal_bTABLEhead\bTABLEhead
+\overloaded\permanent\let\tabl_x_normal_eTABLEhead\eTABLEhead
+\overloaded\permanent\let\tabl_x_normal_bTABLEnext\bTABLEnext
+\overloaded\permanent\let\tabl_x_normal_eTABLEnext\eTABLEnext
+\overloaded\permanent\let\tabl_x_normal_bTABLEfoot\bTABLEfoot
+\overloaded\permanent\let\tabl_x_normal_eTABLEfoot\eTABLEfoot
+\overloaded\permanent\let\tabl_x_normal_bTABLEbody\bTABLEbody
+\overloaded\permanent\let\tabl_x_normal_eTABLEbody\eTABLEbody
+\overloaded\permanent\let\tabl_x_normal_bTR \bTR
+\overloaded\permanent\let\tabl_x_normal_eTR \eTR
+\overloaded\permanent\let\tabl_x_normal_bTD \bTD
+\overloaded\permanent\let\tabl_x_normal_eTD \eTD
+\overloaded\permanent\let\tabl_x_normal_bTH \bTH
+\overloaded\permanent\let\tabl_x_normal_eTH \eTH
+\overloaded\permanent\let\tabl_x_normal_setupTABLE\setupTABLE
+\overloaded\permanent\let\tabl_x_normal_bTABLE \bTABLE
+\overloaded\permanent\let\tabl_x_normal_eTABLE \eTABLE
+
+\permanent\protected\def\restoreTABLEfromxtable
+ {\enforced\let\bTABLEhead\tabl_x_normal_bTABLEhead
+ \enforced\let\eTABLEhead\tabl_x_normal_eTABLEhead
+ \enforced\let\bTABLEnext\tabl_x_normal_bTABLEnext
+ \enforced\let\eTABLEnext\tabl_x_normal_eTABLEnext
+ \enforced\let\bTABLEfoot\tabl_x_normal_bTABLEfoot
+ \enforced\let\eTABLEfoot\tabl_x_normal_eTABLEfoot
+ \enforced\let\bTABLEbody\tabl_x_normal_bTABLEbody
+ \enforced\let\eTABLEbody\tabl_x_normal_eTABLEbody
+ \enforced\let\bTR \tabl_x_normal_bTR
+ \enforced\let\eTR \tabl_x_normal_eTR
+ \enforced\let\bTD \tabl_x_normal_bTD
+ \enforced\let\eTD \tabl_x_normal_eTD
+ \enforced\let\bTH \tabl_x_normal_bTH
+ \enforced\let\eTH \tabl_x_normal_eTH
+ \enforced\let\setupTABLE\tabl_x_normal_setupTABLE
+ \enforced\let\bTABLE \tabl_x_normal_bTABLE
+ \enforced\let\eTABLE \tabl_x_normal_eTABLE}
+
+\permanent\protected\def\mapTABLEtoxtable
+ {\enforced\let\bTABLEhead\startxtablehead
+ \enforced\let\eTABLEhead\stopxtablehead
+ \enforced\let\bTABLEnext\startxtablefoot
+ \enforced\let\eTABLEnext\stopxtablefoot
+ \enforced\let\bTABLEfoot\startxtablefoot
+ \enforced\let\eTABLEfoot\stopxtablefoot
+ \enforced\let\bTABLEbody\startxtablebody
+ \enforced\let\eTABLEbody\stopxtablebody
+ \enforced\let\bTR \startxrow
+ \enforced\let\eTR \stopxrow
+ \enforced\let\bTD \startxcell
+ \enforced\let\eTD \stopxcell
+ \enforced\let\bTH \tabl_x_TABLE_TH_start_cell
+ \enforced\let\eTH \tabl_x_TABLE_TH_stop_cell
+ \enforced\let\setupTABLE\tabl_x_TABLE_setup
+ \enforced\let\bTABLE \tabl_x_TABLE_start
+ \enforced\let\eTABLE \tabl_x_TABLE_stop}
+
+\popoverloadmode
+
+\permanent\protected\def\tabl_x_TABLE_TH_start_cell
+ {\startxcellgroup[\c!foregroundstyle=\v!bold]%
+ \startxcell}
+
+\permanent\protected\def\tabl_x_TABLE_TH_stop_cell
+ {\stopxcell
+ \stopxcellgroup}
+
+\permanent\protected\tolerant\def\tabl_x_TABLE_setup[#settings]%
+ {\ifarguments\or
+ %\ifparameter#1\or
+ \setupxtable[#settings]%
+ \fi}
+
+\permanent\protected\tolerant\def\tabl_x_TABLE_start[#settings]%
+ {\bgroup
+ \ifarguments\or
+ %\ifparameter#1\or
+ \tabl_x_prepare{#settings}%
+ \fi
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process\zerocount}
+
+\permanent\protected\def\tabl_x_TABLE_stop
+ {\stopxtable}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-xtb.mklx b/tex/context/base/mkiv/tabl-xtb.mklx
new file mode 100644
index 000000000..b54685863
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-xtb.mklx
@@ -0,0 +1,983 @@
+% macros=mkvi
+
+%D \module
+%D [ file=tabl-xtb,
+%D version=2011.10.26,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Xtreme,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Xtreme}
+
+\registerctxluafile{tabl-xtb}{}
+
+% todo:
+%
+% - yes or no: foregroundstyle/color <- style/color
+% - template alignment
+% - maybe split horizontal (a la linetables)
+% - before/after and wrapping (linecorrection)
+% - maybe also some before/after commands
+% - maybe correction when non float usage
+% - tagging needs to be checked
+% - maybe only tag the box
+% - scale to fit
+%
+% - buffers permit verbatim but are not always handy
+
+%D This module started as an afternoon experiment and surprisingly could be
+%D mostly finished the same evening. Of course it builds upon existing
+%D functionality. The main reason for writing it is that we occasionally
+%D run into pretty large tables that take tens of pages and need to be split
+%D into floats. Speed is one issue there, avoiding to use vsplit is another.
+%D
+%D \starttyping
+%D \definextable [tag] | [tag][parent]
+%D \setupxtable [settings] | [tag][settings]
+%D
+%D \startxtable[tag|settings]
+%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot
+%D \startxrowgroup[tag|settings]
+%D \startxrow[settings]
+%D \startxcellgroup[tag|settings]
+%D \startxcell[settings] ... \stopxcell
+%D \stopxcellgroup
+%D \stopxrow
+%D \startxrowgroup
+%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot
+%D \stopxtable
+%D \stoptyping
+%D
+%D See xtables-001.tex etc for some examples.
+
+% We can avoid some checking by using the fastoptionalcheckcs helpers
+% instead of dosingleempty but the speed gain is neglectable.
+
+\unprotect
+
+% option=stretch : equal distribution
+% option={stretch,width} : proportional distribution
+% option={max} : prefer max over forced width/height
+%
+% cells: option=fixed : nils autostretch (not yet complete)
+
+% \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged {...}
+%
+% \let\tsplitbeforeresult\donothing
+% \let\tsplitafterresult \donothing
+% \let\tsplitinbetween \donothing
+% \let\tsplitbefore \donothing
+% \let\tsplitafter \donothing
+% \let\postprocesstsplit \donothing
+
+\let\dotagxtablecell \relax % names will change
+\let\dotagxtablesignal\relax % names will change
+
+\appendtoks
+ \def\dotagxtablecell
+ {\clf_settagtablecell
+ \numexpr\tablecellrows\relax
+ \numexpr\tablecellcolumns\relax
+ \numexpr\raggedstatus\relax}%
+ \def\dotagxtablesignal
+ {\signalcharacter}% not used
+\to \everyenableelements
+
+\newdimen\d_tabl_x_width
+\newdimen\d_tabl_x_height
+\newdimen\d_tabl_x_depth % not used
+\newdimen\d_tabl_x_distance
+\newcount\c_tabl_x_nx
+\newcount\c_tabl_x_ny
+\newcount\c_tabl_x_mode
+\newbox \b_tabl_x
+\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft
+\newdimen\d_tabl_x_final_width
+\newcount\c_tabl_x_nesting
+\newcount\c_tabl_x_skip_mode % 1 = skip
+\newdimen\d_tabl_x_textwidth
+\newcount\c_tabl_x_swapped
+\newcount\c_tabl_x_swapped_max
+
+\let\m_tabl_x_swapped_settings\empty
+
+\aliased\let\currentxtablerow \clf_x_table_r
+\aliased\let\currentxtablecolumn\clf_x_table_c
+
+% \setupxtable[one][parent][a=b,c=d]
+% \setupxtable[one] [a=b,c=d]
+% \setupxtable [a=b,c=d]
+
+\installcorenamespace{xtable}
+\installcorenamespace{xtablecheck}
+\installcorenamespace{xtableswap}
+
+\installframedautocommandhandler \??xtable {xtable} \??xtable
+
+\appendtoks
+ \checkxtableparent % so we can deal with undefined settings, not that it's efficient
+\to \everysetupxtable
+
+\setupxtable[%
+ \c!nr=\plusone,
+ \c!nc=\plusone,
+ \c!nx=\plusone, % slow
+ \c!ny=\plusone, % slow
+ \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE
+ \c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ % \c!framecolor=\s!black,
+ % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere
+ % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere
+ % \c!bodyfont=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!maxwidth=8\emwidth,
+ \c!autowidth=\v!yes, % controls framed
+ \c!rulethickness=\linewidth,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!no,
+ \c!split=\v!auto, % a number will take that many lines
+ \c!splitoffset=\zeropoint, % extra space taken
+ \c!aligncharacter=\v!no,
+ \c!alignmentcharacter={,},
+ \c!alignmentleftsample=,
+ \c!alignmentrightsample=,
+ \c!alignmentleftwidth=\zeropoint,
+ \c!alignmentrightwidth=\zeropoint,
+ % \c!option=, % \v!stretch {\v!stretch,\v!width}
+ % \c!footer=,
+ % \c!header=,
+ \c!spaceinbetween=,
+ \c!textwidth=\v!local, % was \hsize,
+ \c!textheight=\vsize, % used for vertical spread
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+]
+
+\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting}
+\let\tabl_x_current_buffer\empty
+
+\permanent\protected\def\startxtable{\tabl_x_start_table}
+
+\protected\tolerant\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings]
+ {\bgroup
+ \tabl_x_prepare{#settings}%
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process\zerocount}
+
+% \permanent\protected\aliased\startxtable\tabl_x_start_table
+
+\aliased\permanent\let\stopxtable\relax
+
+% These direct buffers can be somewhat faster but it's probably neglectable.
+% Anyway, no nesting is supported as we then need to catch (e.g.) rows and
+% keep track of nesting and have a more complex redefinition of nested
+% instanced \unknown\ it's not worth the trouble. Only use them when you
+% really need them and use the embeddedxtable command when nesting them.
+% Implementing nesting would be slower than not using direct buffers.
+
+\permanent\tolerant\protected\def\processxtablebuffer[#name]%
+ {\bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{#name}%
+ \tabl_x_get_buffer % settings
+ \tabl_x_process}
+
+\protected\tolerant\def\tabl_x_start_ignore[#settings]%
+ {}
+
+\protected\tolerant\def\tabl_x_process_buffer[#settings]%
+ {\tabl_x_prepare{#settings}%
+ \let\tabl_x_start_table\tabl_x_start_ignore
+ \gobbleuntil\stopxtable} % nested xtables are not supported,
+
+%D A bonus: you have to use the following construct inside a macro or
+%D direct buffer.
+
+\permanent\tolerant\protected\def\startembeddedxtable[#settings]#;#content\stopembeddedxtable
+ {\tabl_x_prepare{#settings}%
+ \clf_assignbuffer{embedded_x_table}{\detokenize{#content}}\catcodetable\relax
+ \bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{embedded_x_table}%
+ \tabl_x_process}
+
+\aliased\permanent\let\stopembeddedxtable\relax
+
+%D We can also define xtables.
+
+\appendtoks
+ \permanent\setuevalue{\e!start\currentxtable}{\tabl_x_start_named[\currentxtable]}%
+ \permanent\setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}%
+\to \everydefinextable
+
+\protected\def\tabl_x_start_named[#tag]#spacer[#settings]%
+ {\bgroup
+ \edef\currentxtable{#tag}%
+ \advance\c_tabl_x_nesting\plusone
+ \dostarttaggedchained\t!table\empty\??xtable
+ \setupcurrentxtable[#settings]%
+ \tabl_x_check_textwidth
+ %\forgetall % else whitespace mess
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process\zerocount}}
+
+\protected\def\tabl_x_stop_named
+ {}
+
+%D Now we come to processing:
+
+\protected\def\tabl_x_check_textwidth
+ {\edef\p_textwidth{\xtableparameter\c!textwidth}%
+ \ifx\p_textwidth\v!local
+ \d_tabl_x_textwidth\availablehsize
+ \else
+ \d_tabl_x_textwidth\p_textwidth
+ \fi}
+
+\newtoks\everypreparextable
+
+\protected\def\tabl_x_prepare#settings%
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttaggedchained\t!table\empty\??xtable
+ \tabl_x_set_checked{#settings}%
+ \tabl_x_check_textwidth
+ \the\everypreparextable
+ }% else whitespace mess
+
+\def\tabl_x_get_buffer
+ {\clf_gettexbuffer{\tabl_x_current_buffer}}
+
+\let\tabl_x_start_row_yes \relax
+\let\tabl_x_start_row_nop \relax
+\let\tabl_x_stop_row \relax
+\let\tabl_x_start_cell_yes\relax
+\let\tabl_x_start_cell_nop\relax
+\let\tabl_x_stop_cell \relax
+
+\newtoks\t_table_x_cleanup
+
+\protected\def\tabl_x_process
+ {\begingroup % *
+ \forgetall % moved here
+ \dontcomplain % for the moment here till we figure out where we get the overflow
+ \usebodyfontparameter\xtableparameter
+ \setbox\scratchbox\vbox
+ {\doifsomething{\xtableparameter\c!spaceinbetween}{\blank[\xtableparameter\c!spaceinbetween]}}%
+ \clf_x_table_create
+ option {\xtableparameter\c!option}%
+ textwidth \d_tabl_x_textwidth
+ textheight \dimexpr\xtableparameter\c!textheight\relax
+ maxwidth \dimexpr\xtableparameter\c!maxwidth\relax
+ lineheight \openlineheight
+ columndistance \dimexpr\xtableparameter\c!columndistance\relax
+ leftmargindistance \dimexpr\xtableparameter\c!leftmargindistance\relax
+ rightmargindistance \dimexpr\xtableparameter\c!rightmargindistance\relax
+ rowdistance \ht\scratchbox
+ header {\xtableparameter\c!header}%
+ footer {\xtableparameter\c!footer}%
+ \relax
+ %
+ \letxtableparameter\c!option\empty
+ % not so nice but needed as we use this in the setup
+ \linewidth\xtableparameter\c!rulethickness\relax
+ % so we freeze it
+ \c_tabl_x_swapped_max\zerocount
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width
+ \settrialtypesetting
+ \tabl_x_get_buffer
+ \ifcase\c_tabl_x_swapped_max
+ \else
+ \tabl_x_flush_swapped
+ \fi
+ \clf_x_table_reflow_width
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height
+ \settrialtypesetting
+ \ifcase\c_tabl_x_swapped_max
+ \tabl_x_get_buffer
+ \else
+ \tabl_x_flush_swapped
+ \fi
+ \clf_x_table_reflow_height
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_construct
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_construct
+ \ifcase\c_tabl_x_swapped_max
+ \tabl_x_get_buffer
+ \else
+ \tabl_x_flush_swapped
+ \fi
+ \clf_x_table_construct
+ \endgroup
+ \endgroup % *
+ \ifinsidesplitfloat
+ \tabl_x_flush_float_split
+ \orelse\ifinsidefloat
+ \tabl_x_flush_float_normal
+ \else
+ \tabl_x_flush_text_checked
+ \fi
+ \clf_x_table_cleanup
+ \dostoptagged
+ \resetbuffer[\tabl_x_current_buffer]%
+ \resetcharacteralign
+ \the\t_table_x_cleanup
+ \egroup}
+
+% text flow split modes
+
+\installcorenamespace{xtableflushsplit}
+
+\protected\def\tabl_x_flush_text_checked
+ {\expandnamespaceparameter\??xtableflushsplit\xtableparameter\c!split\v!no}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!yes}%
+ {\clf_x_table_flush
+ method {\v!split}%
+ \relax}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!no}%
+ {% \noindent % gives extra line after table
+ % \noindentation % messes up the next indentation
+ % \dontleavehmode % no leftskip
+ \kern\zeropoint % yet another guess
+ \ignorespaces
+ \clf_x_table_flush
+ method {\v!normal}%
+ \relax
+ \removeunwantedspaces}
+
+% in text flow: headers and footers get repeated
+
+\setvalue{\??xtableflushsplit\v!repeat}%
+ {\doloop
+ {\clf_x_table_flush
+ method {\v!split}%
+ height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi
+ \relax
+ \ifcase\c_tabl_x_state
+ \exitloop
+ \else
+ \page
+ \fi}}
+
+% \setvalue{\??xtableflushsplit\v!setups}%
+% {\directsetup{xtable:split:user}}
+%
+% \startsetups[xtable:split:user]
+% \doloop {
+% \xtablesplitflush % uses \xtablesplitvsize (a macro)
+% \ifcase\xtablesplitstate
+% \exitloop
+% \else
+% \page
+% \fi
+% }
+% \stopsetups
+%
+% \protected\def\xtablesplitflush
+% {\clf_x_table_flush
+% method {\v!split}%
+% height \dimexpr\xtablesplitvsize\relax
+% \relax}
+%
+% \def\xtablesplitvsize
+% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi}
+%
+% \let\xtablesplitstate\c_tabl_x_state
+
+\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it
+
+\protected\def\tabl_x_flush_float_normal
+ {\clf_x_table_flush
+ method {\v!normal}%
+ \relax}
+
+\protected\def\tabl_x_flush_float_split
+ {\resetdirecttsplit
+ \edef\extrasplitfloatlines {\xtableparameter\c!split}%
+ \edef\tsplitminimumfreespace{\the\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax}%
+ % \edef\tsplitminimumfreelines{2}% not needed here as we're precise enough
+ \let\tsplitdirectsplitter\tabl_x_split_splitter
+ \let\tsplitdirectwidth \d_tabl_x_final_width
+ \handledirecttsplit}
+
+\protected\def\tabl_x_split_splitter#height%
+ {\setbox\tsplitresult\vbox
+ {\clf_x_table_flush
+ method {\v!split}%
+ height \dimexpr#height\relax
+ \relax}%
+ \ifcase\c_tabl_x_state
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \fi}
+
+% \permanent\protected\def\startxrow
+% {\begingroup
+% \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+% \permanent\protected\def\stopxrow
+% {\tabl_x_stop_row
+% \endgroup}
+
+\protected\def\tabl_x_start_row_reflow_width_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \clf_x_table_next_row}
+
+\protected\def\tabl_x_start_row_reflow_width_nop
+ {\clf_x_table_next_row}
+
+\protected\def\tabl_x_stop_row_reflow_width
+ {}
+
+\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes
+\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop
+\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width
+
+\protected\def\tabl_x_start_row_construct_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \dostarttagged\t!tablerow\empty
+ \clf_x_table_next_row_option{\xtableparameter\c!samepage}}
+
+\protected\def\tabl_x_start_row_construct_nop
+ {\dostarttagged\t!tablerow\empty
+ \clf_x_table_next_row}
+
+\protected\def\tabl_x_stop_row_construct
+ {\clf_x_table_finish_row
+ \dostoptagged}
+
+\permanent\protected\def\dummyxcell
+ {\begingroup
+ \let\inheritedxtableframed\relax
+ \tabl_x_start_cell_nop
+ \tabl_x_stop_cell
+ \endgroup}
+
+\def\tabl_x_setup_character_align
+ {\edef\p_left {\directxtableparameter\c!alignmentleftsample}%
+ \edef\p_right{\directxtableparameter\c!alignmentrightsample}%
+ \ifx\p_left\empty
+ \scratchdimenone\dimexpr\directxtableparameter\c!alignmentleftwidth\relax
+ \else
+ \setbox\scratchbox\hbox{\p_left}%
+ \scratchdimenone\wd\scratchbox
+ \fi
+ \ifx\p_right\empty
+ \scratchdimentwo\dimexpr\directxtableparameter\c!alignmentrightwidth\relax
+ \else
+ \setbox\scratchbox\hbox{\p_right}%
+ \scratchdimentwo\wd\scratchbox
+ \fi
+ \clf_setcharacteraligndetail
+ \clf_x_table_c
+ {\directxtableparameter\c!alignmentcharacter}%
+ \scratchdimenone
+ \scratchdimentwo
+ \relax}
+
+\newtoks\t_tabl_x_every_cell
+
+% \appendtoks
+% \inhibitblank % already in framed
+% \to \t_tabl_x_every_cell
+
+\appendtoks
+ \edef\p_characteralign{\directxtableparameter\c!aligncharacter}%
+ \ifx\p_characteralign\v!yes
+ \ifcase\clf_x_table_r\or
+ \tabl_x_setup_character_align
+ \fi
+ \signalcharacteralign\clf_x_table_c\clf_x_table_r
+ \fi
+\to \t_tabl_x_every_cell
+
+\protected\def\tabl_x_begin_of_cell
+ {\the\t_tabl_x_every_cell
+ \everypar{\delayedbegstrut}}
+
+\protected\def\tabl_x_end_of_cell
+ {\ifhmode
+ \delayedendstrut
+ \par
+ \else
+ \par
+ \ifdim\prevdepth<\zeropoint % =-1000pt ?
+ \vskip-\strutdp
+ \else
+ \removebottomthings
+ \fi
+ \fi}
+
+% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes
+% obsolete some day. The let as well as the direct speed things up a bit. We
+% could also consider a \defaultxtableparameter.
+%
+% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone}
+% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone}
+%
+% Although this becomes kind of messy. It saves already time that we only check
+% for it when we have settings.
+
+% \def\tabl_x_set_hsize
+% {\hsize.25\maxdimen} % let's be reasonable
+
+% \def\tabl_x_set_hsize
+% {\edef\p_width{\xtableparameter\c!width}%
+% \ifx\p_width\empty
+% \hsize.25\maxdimen % is this really needed
+% \fi}
+
+\let\tabl_x_set_hsize\relax
+
+\protected\def\tabl_x_start_cell_reflow_width_yes[#settings]%
+ {\setbox\b_tabl_x\hpack\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ %
+ \letxtableparameter\c!nx\plusone
+ \letxtableparameter\c!ny\plusone
+ \letxtableparameter\c!nc\plusone
+ \letxtableparameter\c!nr\plusone
+ %
+ \setupcurrentxtable[#settings]%
+ %
+ \c_tabl_x_nx\directxtableparameter\c!nc\relax
+ \c_tabl_x_ny\directxtableparameter\c!nr\relax
+ \ifnum\c_tabl_x_nx=\plusone
+ \c_tabl_x_nx\directxtableparameter\c!nx\relax
+ \fi
+ \ifnum\c_tabl_x_ny=\plusone
+ \c_tabl_x_ny\directxtableparameter\c!ny\relax
+ \fi
+ %
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \clf_x_table_init_reflow_width_option{\xtableparameter\c!option}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\protected\def\tabl_x_start_cell_reflow_width_nop
+ {\setbox\b_tabl_x\hpack\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \c_tabl_x_nx\plusone
+ \c_tabl_x_ny\plusone
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \clf_x_table_init_reflow_width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\protected\def\tabl_x_stop_cell_reflow_width
+ {\tabl_x_end_of_cell
+ \egroup
+ \egroup
+ \clf_x_table_set_reflow_width}
+
+\protected\def\tabl_x_start_cell_reflow_height_yes[#settings]%
+ {\setbox\b_tabl_x\hpack\bgroup
+ \clf_x_table_init_reflow_height
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \setupcurrentxtable[#settings]%
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\protected\def\tabl_x_start_cell_reflow_height_nop
+ {\setbox\b_tabl_x\hpack\bgroup
+ \clf_x_table_init_reflow_height
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\protected\def\tabl_x_stop_cell_reflow_height
+ {\ifcase\c_tabl_x_skip_mode
+ \tabl_x_end_of_cell
+ \egroup
+ \fi
+ \egroup
+ \clf_x_table_set_reflow_height}
+
+\protected\def\tabl_x_start_cell_construct_yes[#settings]%
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hpack\bgroup
+ \setupcurrentxtable[#settings]%
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \clf_x_table_init_construct
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\protected\def\tabl_x_start_cell_construct_nop
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hpack\bgroup
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height (commenting it ... nice option)
+ \clf_x_table_init_construct
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\protected\def\tabl_x_stop_cell_construct
+ {\tabl_x_end_of_cell
+ \egroup
+ \dotagxtablesignal % harmless spot
+ \egroup
+ \clf_x_table_set_construct
+ \dostoptagged}
+
+% \permanent\tolerant\protected\def\startxcellgroup[#settings]%
+% {\begingroup
+% \ifarguments\or
+% \tabl_x_set_checked{#settings}%
+% \fi}
+%
+% \permanent\protected\def\stopxcellgroup
+% {\endgroup}
+%
+% \permanent\tolerant\protected\def\startxrowgroup[#settings]%
+% {\begingroup
+% \ifarguments\or
+% \tabl_x_set_checked{#settings}%
+% \fi}
+%
+% \permanent\protected\def\stopxrowgroup
+% {\dostoptagged
+% \endgroup}
+
+\protected\def\tabl_x_set_checked#settings%
+ {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+ \edef\currentxtable{#settings}%
+ \else
+ \setupcurrentxtable[#settings]%
+ \fi}
+
+\permanent\protected\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \tabl_x_start_partition}
+\permanent\protected\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \tabl_x_start_partition}
+\permanent\protected\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\tabl_x_start_partition}
+\permanent\protected\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \tabl_x_start_partition}
+
+\permanent\tolerant\protected\def\tabl_x_start_partition[#settings]%
+ {\ifarguments\or
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\protected\def\tabl_x_stop_partition
+ {\endgroup}
+
+\permanent\aliased\let\stopxtablehead\tabl_x_stop_partition
+\permanent\aliased\let\stopxtablefoot\tabl_x_stop_partition
+\permanent\aliased\let\stopxtablenext\tabl_x_stop_partition
+\permanent\aliased\let\stopxtablebody\tabl_x_stop_partition
+
+%D This is an experiment! Beware: you can create loops by using nested
+%D references to already chained settings.
+%D
+%D \startbuffer
+%D \setupxtable[suffix][align=middle,foregroundcolor=red]
+%D \setupxtable[blabla][foregroundstyle=slanted]
+%D \setupxtable[crap] [foregroundcolor=blue]
+%D \setupxtable[bold] [crap][foregroundstyle=bold]
+%D
+%D \startxtable[frame=off]
+%D \startxtablehead
+%D \startxrow[bold]
+%D \startxcell[suffix] a 0 \stopxcell
+%D \startxcell[blabla] a 1 \stopxcell
+%D \startxcell a 2 \stopxcell
+%D \stopxrow
+%D \stopxtablehead
+%D \startxtablebody
+%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow
+%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow
+%D \stopxtablebody
+%D \stopxtable
+%D \stopbuffer
+%D
+%D \typebuffer \placetable{}{\getbuffer}
+
+\appendtoks
+ \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent
+\to \everysetupxtable
+
+% \definefontfamily[newtimes][serif][TeX Gyre Termes]
+% \setupxtable[newtimes][foregroundstyle=\newtimes]
+% \startxcell[newtimes] ...\stopxcell
+% \startxcell[foregroundstyle=\newtimes] ...\stopxcell
+
+% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+% % \ifcsname\??xtablecheck#tag\endcsname
+% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords
+% \expandafter\whatever % but more tolerant for tricky key=value
+% \else
+% \expandafter\whatever
+% \fi[#tag]
+
+% groups
+
+\permanent\protected\def\startxgroup
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_group_delayed_one\relax}
+
+\permanent\protected\def\stopxgroup
+ {\endgroup}
+
+\protected\def\tabl_x_start_group_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_group_delayed_two
+ \else
+ \expandafter\setupcurrentxtable
+ \fi[#tag]}
+
+\protected\def\tabl_x_start_group_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\setupcurrentxtable\relax}
+
+\aliased\let\startxrowgroup \startxgroup
+\aliased\let\stopxrowgroup \stopxgroup
+\aliased\let\startxcellgroup\startxgroup
+\aliased\let\stopxcellgroup \stopxgroup
+
+% cells (maybe also check for 1 etc but it becomes messy)
+
+\permanent\protected\def\startxcell
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop}
+
+\protected\def\tabl_x_start_cell_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_cell_delayed_two
+ \else
+ \expandafter\tabl_x_start_cell_yes
+ \fi[#tag]}
+
+\protected\def\tabl_x_start_cell_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\permanent\protected\def\stopxcell
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% rows
+
+\permanent\protected\def\startxrow
+ {\begingroup
+ \doifelsenextoptionalcs\tabl_x_start_row_delayed_one\tabl_x_start_row_nop}
+
+\protected\def\tabl_x_start_row_delayed_one[#tag]%
+ {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname
+ \expandafter\tabl_x_start_row_delayed_two
+ \else
+ \expandafter\tabl_x_start_row_yes
+ \fi[#tag]}
+
+\permanent\protected\def\tabl_x_start_row_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\permanent\protected\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+%D A bonus, not advertised but some like it this way:
+
+\protected\def\tabl_x_nc
+ {\startxrow
+ \enforced\let\NC\tabl_x_nc_next
+ \enforced\let\NR\tabl_x_nr
+ \startxcell}
+
+\protected\def\tabl_x_nc_next
+ {\stopxcell
+ \startxcell}
+
+\protected\def\tabl_x_nr
+ {\stopxcell
+ \stopxrow
+ \enforced\let\NC\tabl_x_nc}
+
+\appendtoks
+ \enforced\let\NC\tabl_x_nc
+ \enforced\let\NR\tabl_x_nr
+\to \everypreparextable
+
+%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting.
+
+\protected\def\tabl_x_c_cell_start#settings%
+ {\begingroup
+ \tabl_x_set_checked{#settings}%
+ \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\protected\def\tabl_x_c_cell_stop
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% \protected\def\dummyxcell
+% {\tabl_x_start_cell_nop
+% \tabl_x_stop_cell}
+
+\mutable\let\t_tabl_x_swapped\relax
+
+\def\tabl_x_flush_swapped
+ {\dorecurse\c_tabl_x_swapped_max
+ {\expandafter
+ \startxrow
+ \the\csname\??xtableswap##1\endcsname\relax
+ \stopxrow}}
+
+\def\tabl_x_collect_allocate
+ {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname
+ \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname}
+
+\def\tabl_x_collect_advance
+ {\global\advance\c_tabl_x_swapped\plusone
+ \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max
+ \global\c_tabl_x_swapped_max\c_tabl_x_swapped
+ \fi
+ \mutable\expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname
+ \ifx\t_tabl_x_swapped\relax
+ \tabl_x_collect_allocate
+ \fi}
+
+\protected\def\tabl_x_collect_cell_start
+ {\doifelsenextoptionalcs
+ \tabl_x_collect_cell_start_yes
+ \tabl_x_collect_cell_start_nop}
+
+\def\tabl_x_collect_cell_start_nop#content\stopxcell
+ {\tabl_x_collect_advance
+ \ifx\m_tabl_x_swapped_settings\empty
+ \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}%
+ \else
+ \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}%
+ \fi}
+
+\def\tabl_x_collect_cell_start_yes[#settings]#content\stopxcell
+ {\tabl_x_collect_advance
+ \ifx\m_tabl_x_swapped_settings\empty
+ \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}%
+ \else
+ \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}%
+ \fi
+ \getdummyparameters[\c!ny=1,#settings]%
+ \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax
+ \ifcase\scratchcounter\else
+ \dorecurse\scratchcounter\tabl_x_collect_advance
+ \fi}
+
+\permanent\tolerant\protected\def\startxcolumn[#1]%
+ {\begingroup
+ \global\c_tabl_x_swapped\zerocount
+ \enforced\let\startxcell\tabl_x_collect_cell_start
+ \enforced\let\stopxcell \relax
+ \xdef\m_tabl_x_swapped_settings{#1}}
+
+\permanent\protected\def\stopxcolumn
+ {\endgroup}
+
+\appendtoks
+ \dorecurse\c_tabl_x_swapped_max
+ {\global\csname\??xtableswap\number#1\endcsname\emptytoks}%
+\to \t_table_x_cleanup
+
+%D \startbuffer
+%D \setupxtable[one][foregroundcolor=red]
+%D \setupxtable[two][foregroundcolor=blue]
+%D
+%D \startlinecorrection
+%D \startxtable
+%D \startxrow[one]
+%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
+%D \startxcell Row 1, Column 2 \stopxcell
+%D \startxcell Row 1, Column 3 \stopxcell
+%D \stopxrow
+%D \startxrow[two]
+%D \startxcell Row 2, Column 1 \stopxcell
+%D \startxcell Row 2, Column 2 \stopxcell
+%D \startxcell Row 2, Column 3 \stopxcell
+%D \stopxrow
+%D \stopxtable
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \startxtable
+%D \startxcolumn[one]
+%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
+%D \startxcell Row 1, Column 2 \stopxcell
+%D \startxcell Row 1, Column 3 \stopxcell
+%D \stopxcolumn
+%D \startxcolumn[two]
+%D \startxcell Row 2, Column 1 \stopxcell
+%D \startxcell Row 2, Column 2 \stopxcell
+%D \startxcell Row 2, Column 3 \stopxcell
+%D \stopxcolumn
+%D \stopxtable
+%D \stoplinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua
index 033672f45..45c0c3239 100644
--- a/tex/context/base/mkiv/task-ini.lua
+++ b/tex/context/base/mkiv/task-ini.lua
@@ -53,7 +53,6 @@ appendaction("processors", "fonts", "typesetters.fontkerns.handler",
appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nonut", "enabled" )
appendaction("processors", "fonts", "builders.kernel.ligaturing", nil, "nut", "disabled" )
appendaction("processors", "fonts", "builders.kernel.kerning", nil, "nut", "disabled" )
-appendaction("processors", "fonts", "builders.kernel.cleanup", nil, "nut", "enabled" )
appendaction("processors", "fonts", "nodes.handlers.stripping", nil, "nut", "disabled" )
appendaction("processors", "fonts", "nodes.handlers.flatten", nil, "nut", "disabled" )
appendaction("processors", "fonts", "fonts.goodies.colorschemes.coloring", nil, "nut", "disabled" )
diff --git a/tex/context/base/mkiv/toks-aux.lmt b/tex/context/base/mkiv/toks-aux.lmt
index c77c868fc..e1a4e89b3 100644
--- a/tex/context/base/mkiv/toks-aux.lmt
+++ b/tex/context/base/mkiv/toks-aux.lmt
@@ -5,113 +5,172 @@ if not modules then modules = { } end modules ['toks-aux'] = {
license = "see context related readme files"
}
-if CONTEXTLMTXMODE > 0 then
+local type, tostring = type, tostring
+local max = math.max
+local formatters, gsub, char = string.formatters, string.gsub, string.char
+local concat = table.concat
- local type, tostring = type, tostring
- local max = math.max
- local formatters, gsub = string.formatters, string.gsub
+local function flags(t)
+ if type(t) == "string" then
+ t = token.create(t)
+ end
+ local r = { }
+ if t.frozen then r[#r+1] = "frozen" end
+ if t.permanent then r[#r+1] = "permanent" end
+ if t.immutable then r[#r+1] = "immutable" end
+ if t.primitive then r[#r+1] = "primitive" end
+ if t.mutable then r[#r+1] = "mutable" end
+ if t.noaligned then r[#r+1] = "noaligned" end
+ if t.instance then r[#r+1] = "instance" end
+ if t.tolerant then r[#r+1] = "tolerant" end
+ if t.protected then r[#r+1] = "protected" end
+ return r
+end
+
+tokens.flags= flags
- interfaces.implement {
- name = "showluatokens",
- public = true,
- protected = true,
- actions = function()
- local f0 = formatters["%s: %s"]
- local nl = logs.newline
- local wr = logs.writer
- local t = token.peek_next() -- local t = token.scan_next() token.put_back(t)
- local n = ""
- local w = ""
- local c = t.cmdname
- if c == "left_brace" then
- w = "given token list"
- t = token.scan_toks(false)
- elseif c == "register_toks" then
- token.scan_next()
- w = "token register"
- n = t.csname or t.index
- t = tex.gettoks(n,true)
- elseif c == "internal_toks" then
- token.scan_next()
- w = "internal token variable"
- n = t.csname or t.index
- t = tex.gettoks(n,true)
+interfaces.implement {
+ name = "showluatokens",
+ public = true,
+ protected = true,
+ actions = function()
+ local f0 = formatters["%s: %s"]
+ local nl = logs.newline
+ local wr = logs.writer
+ local t = token.peek_next() -- local t = token.scan_next() token.put_back(t)
+ local n = ""
+ local w = ""
+ local c = t.cmdname
+ if c == "left_brace" then
+ w = "given token list"
+ t = token.scan_toks(false)
+ elseif c == "register_toks" then
+ token.scan_next()
+ w = "token register"
+ n = t.csname or t.index
+ t = tex.gettoks(n,true)
+ elseif c == "internal_toks" then
+ token.scan_next()
+ w = "internal token variable"
+ n = t.csname or t.index
+ t = tex.gettoks(n,true)
+ else
+ n = token.scan_csname()
+ local r = flags(t)
+ local m = token.get_meaning(n,true)
+ r[#r+1] = "control sequence"
+ if type(m) == "table" then
+ t = m
else
- if t.protected then
- w = "protected control sequence"
- else
- w = "control sequence"
- end
- n = token.scan_csname()
- t = token.get_meaning(n,true)
+ t = { t }
end
- wr(f0(w,n))
- nl()
- if type(t) == "table" then
- local w1 = 4
- local w2 = 1
- local w3 = 3
- local w4 = 3
- for i=1,#t do
- local ti = t[i]
- w1 = max(w1,#tostring(ti.id))
- w2 = max(w2,#tostring(ti.command))
- w3 = max(w3,#tostring(ti.index))
- w4 = max(w4,#ti.cmdname)
+ w = concat(r, " ")
+ end
+ wr(f0(w,n))
+ nl()
+ if type(t) == "table" then
+ local w1 = 4
+ local w2 = 1
+ local w3 = 3
+ local w4 = 3
+ for i=1,#t do
+ local ti = t[i]
+ w1 = max(w1,#tostring(ti.id))
+ w2 = max(w2,#tostring(ti.command))
+ w3 = max(w3,#tostring(ti.index))
+ w4 = max(w4,#ti.cmdname)
+ end
+ local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"]
+ local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"]
+ local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"]
+ for i=1,#t do
+ local ti = t[i]
+ local cs = ti.csname
+ local id = ti.id
+ local ix = ti.index
+ local cd = ti.command
+ local cn = ti.cmdname
+ if cn == "prefix" and not cs then
+ cs = "always enforced"
end
- local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"]
- local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"]
- local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"]
- for i=1,#t do
- local ti = t[i]
- local cs = ti.csname
- local id = ti.id
- local ix = ti.index
- local cd = ti.command
- local cn = gsub(ti.cmdname,"_"," ")
- if cs then
- wr(f1(id,cd,ix,cn,cs))
- elseif cn == "letter" or cn == "other_char" then
- wr(f3(id,cd,ix,cn,ix))
- else
- wr(f2(id,cd,ix,cn))
- if cn == "end_match" then
- wr("-------")
- end
+ cn = gsub(cn,"_"," ")
+ if cs then
+ wr(f1(id,cd,ix,cn,cs))
+ elseif cn == "letter" or cn == "other char" then
+ wr(f3(id,cd,ix,cn,ix))
+ elseif cn == "match" then
+ local s
+ if ix == 32 then s = "optional spacer" -- space
+ elseif ix == 42 then s = "skip spaces" -- *
+ elseif ix == 43 then s = "keep braces" -- +
+ elseif ix == 45 then s = "thrash" -- -
+ elseif ix == 47 then s = "prune" -- /
+ elseif ix == 58 then s = "continue" -- :
+ elseif ix == 59 then s = "quit" -- ;
+ elseif ix == 61 then s = "mandate braces" -- =
+ elseif ix == 94 then s = "keep spaces" -- ^
+ elseif ix == 95 then s = "keep mandate braces" -- _
+ else s = "argument " .. char(ix)
+ end
+ wr(f1(id,cd,ix,cn,s))
+ else
+ wr(f2(id,cd,ix,cn))
+ if cn == "end match" then
+ wr("--------------")
end
end
- nl()
end
+ nl()
end
- }
+ end
+}
- -- For the moment here, will move to initex only (also see node-ini.lua); we need
- -- to actually store these.
+-- For the moment here, will move to initex only (also see node-ini.lua); we need
+-- to actually store these.
- local groupcodes = { }
- local hyphenationcodes = { }
+local groupcodes = { }
+local glyphoptioncodes = { }
+local hyphenationcodes = { }
+local frozenparcodes = { }
+local flagcodes = { }
- for k, v in next, tex.getgroupvalues() do
- groupcodes[k] = gsub(v,"_","")
- end
- for k, v in next, tex.gethyphenationvalues() do
- hyphenationcodes[k] = gsub(v,"_","")
- end
+for k, v in next, tex.getgroupvalues() do
+ groupcodes[k] = gsub(v,"[_ ]","")
+end
+for k, v in next, tex.gethyphenationvalues() do
+ hyphenationcodes[k] = gsub(v,"[_ ]","")
+end
+for k, v in next, tex.getglyphoptionvalues() do
+ glyphoptioncodes[k] = gsub(v,"[_ ]","")
+end
+for k, v in next, tex.getfrozenparvalues() do
+ frozenparcodes[k] = gsub(v,"[_ ]","")
+end
+for k, v in next, tex.getflagvalues() do
+ flagcodes[k] = gsub(v,"[_ ]","")
+end
- if environment.initex then
- local texchardef = tex.chardef
+if environment.initex then
- -- for k, v in next, prefixcodes do texchardef(v .. "prefixcode", k) end
- for k, v in next, groupcodes do texchardef(v .. "groupcode", k) end
- for k, v in next, hyphenationcodes do texchardef(v .. "hyphenationmodecode",k) end
+ local texintegerdef = tex.integerdef
- end
+ for k, v in next, groupcodes do texintegerdef(v .. "groupcode", k,"immutable") end
+ for k, v in next, glyphoptioncodes do texintegerdef(v .. "code", k,"immutable") end
+ for k, v in next, hyphenationcodes do texintegerdef(v .. "hyphenationmodecode",k,"immutable") end
+ for k, v in next, frozenparcodes do texintegerdef("frozen" .. v .. "code", k,"immutable") end
+ for k, v in next, flagcodes do texintegerdef(v .. "flagcode", k,"immutable") end
- groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes))
- hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodescodes))
+end
- tex.groupcodes = groupcodes
- tex.hyphenationcodes = hyphenationcodes
+groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes))
+glyphoptioncodes = utilities.storage.allocate(table.swapped(glyphoptioncodes,glyphoptioncodes))
+hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodes))
+frozenparcodes = utilities.storage.allocate(table.swapped(frozenparcodes, frozenparcodes))
+flagcodes = utilities.storage.allocate(table.swapped(flagcodes, flagcodes))
-end
+tex.groupcodes = groupcodes
+tex.glyphoptioncodes = glyphoptioncodes
+tex.hyphenationcodes = hyphenationcodes
+tex.frozenparcodes = frozenparcodes
+tex.flagcodes = flagcodes
diff --git a/tex/context/base/mkiv/toks-aux.mkiv b/tex/context/base/mkiv/toks-aux.mkiv
index 817a5aba9..f66b51ec5 100644
--- a/tex/context/base/mkiv/toks-aux.mkiv
+++ b/tex/context/base/mkiv/toks-aux.mkiv
@@ -65,8 +65,4 @@
\lastnamedcs\emptytoks
\fi}
-\ifcase\contextlmtxmode \or
- \chardef\discretionarygroupcode = \discgroupcode
-\fi
-
\protect
diff --git a/tex/context/base/mkiv/toks-ini.lmt b/tex/context/base/mkiv/toks-ini.lmt
index cf1edd272..23896883c 100644
--- a/tex/context/base/mkiv/toks-ini.lmt
+++ b/tex/context/base/mkiv/toks-ini.lmt
@@ -72,8 +72,8 @@ tokens.istoken = is_token
tokens.isdefined = is_defined
tokens.defined = is_defined
-tokens.getdata = token.get_data -- only lmtx
-tokens.setdata = token.set_data -- only lmtx
+tokens.getinteger = token.get_integer
+tokens.setinteger = token.set_integer
local bits = {
escape = 0x00000001, -- 2^00
@@ -296,8 +296,14 @@ if setinspector then
cmdname = cmdname,
active = t.active,
expandable = t.expandable,
- protected = t.protected,
frozen = t.frozen,
+ tolerant = t.tolerant,
+ protected = t.protected,
+ primitive = t.primitive,
+ permanent = t.permanent,
+ noaligned = t.noaligned,
+ instance = t.instance,
+ immutable = t.imutable,
user = t.user,
}
end
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index 7f3254dde..7120b47c3 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -66,9 +66,6 @@ tokens.istoken = is_token
tokens.isdefined = is_defined
tokens.defined = is_defined
-tokens.getdata = token.get_data -- only lmtx
-tokens.setdata = token.set_data -- only lmtx
-
local bits = {
escape = 0x00000001, -- 2^00
begingroup = 0x00000002, -- 2^01
diff --git a/tex/context/base/mkiv/trac-deb.lmt b/tex/context/base/mkiv/trac-deb.lmt
index 7a2eba2a0..88d686462 100644
--- a/tex/context/base/mkiv/trac-deb.lmt
+++ b/tex/context/base/mkiv/trac-deb.lmt
@@ -119,7 +119,7 @@ do
local writenl = texio.write_nl
local write = texio.write
- local runtoks = tex.runtoks
+ local runlocal = tex.runlocal
local terminaldata = false
local context = context
@@ -140,7 +140,7 @@ do
terminaldata = false
break
else
- runtoks("t_syst_terminal_data",nil,nil,true) -- obeymode
+ runlocal("t_syst_terminal_data",nil,nil,true) -- obeymode
end
end
end
@@ -284,7 +284,11 @@ function tracers.printerror(specification)
local offset = specification.offset
local endoffile = specification.endoffile
local report = errorreporter(luaerrorline)
- if errortype == errorvalues.eof then
+ if errortype == errorvalues.warning then
+ report("warning error: %s",lasttexerror or "-")
+ busy = false;
+ return;
+ elseif errortype == errorvalues.eof then
report("runaway error: %s",lasttexerror or "-")
if not quitonerror and texio.terminal then
texio.terminal() -- not well tested
@@ -377,7 +381,7 @@ directives.register("system.errorcontext", function(v)
register('show_error_message', nop)
register('show_warning_message', function() processwarning(v) end)
register('intercept_lua_error', function() processerror(v) end)
- register('intercept_tex_error', function(mode,eof) processerror(v,eof) end)
+ register('intercept_tex_error', function(mode,eof) processerror(v,eof) return mode end)
else
register('show_error_message', nil)
register('show_warning_message', nil)
diff --git a/tex/context/base/mkiv/trac-deb.mkiv b/tex/context/base/mkiv/trac-deb.mkiv
index 994c357d0..77f54b5aa 100644
--- a/tex/context/base/mkiv/trac-deb.mkiv
+++ b/tex/context/base/mkiv/trac-deb.mkiv
@@ -13,11 +13,11 @@
\writestatus{loading}{ConTeXt Tracing Macros / Debugger}
-\unprotect
-
%registerctxluafile{trac-lmx}{}
\registerctxluafile{trac-deb}{autosuffix}
+\unprotect
+
\unexpanded\def\breakpoint {\showdebuginfo\wait}
\unexpanded\def\showtrackers {\clf_showtrackers}
@@ -40,14 +40,10 @@
% \enabledirectives[system.showerror]
-\unprotect
-
\ifcase\contextlmtxmode \else
\newtoks \t_syst_terminal_data
% \t_syst_terminal_data {\beginlocalcontrol\clf_fetchterminaldata\endlocalcontrol}
\t_syst_terminal_data {\clf_fetchterminaldata}
\fi
-\protect
-
\protect \endinput
diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua
index 4fbab5cdc..96b69a73e 100644
--- a/tex/context/base/mkiv/trac-log.lua
+++ b/tex/context/base/mkiv/trac-log.lua
@@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['trac-log'] = {
-- In fact all writes could go through lua and we could write the console and
-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go.
+--
+-- This is the version for mtxrun. The alternative functions for the TeX engines
+-- have been separated. In order to keep in sync we use tex specific witer names.
+--
+-- Todo: some cleanup (less local needed).
local next, type, select, print = next, type, select, print
local format, gmatch, find = string.format, string.gmatch, string.find
@@ -17,30 +22,16 @@ local utfchar = utf.char
local datetime = os.date
local openfile = io.open
-local runningtex = tex and (tex.jobname or tex.formatname)
--- local write_nl = texio and texio.write_nl or print
--- local write = texio and texio.write or io.write
-
-local write_nl = runningtex and texio and texio.write_nl or print
-local write = runningtex and texio and texio.write or io.write
+local write_nl = print
+local write = io.write
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
local settings_to_hash = utilities.parsers.settings_to_hash
local sortedkeys = table.sortedkeys
--- variant is set now
-
local variant = "default"
--- local variant = "ansi"
-
--- todo: less categories, more subcategories (e.g. nodes)
--- todo: split into basics and ctx specific
-
---[[ldx--
-<p>This is a prelude to a more extensive logging module. We no longer
-provide <l n='xml'/> based logging as parsing is relatively easy anyway.</p>
---ldx]]--
+----- variant = "ansi"
logs = logs or { }
local logs = logs
@@ -53,23 +44,6 @@ webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
wiki : http://contextgarden.net
]]
--- -- we extend the formatters:
---
--- function utilities.strings.unichr(s) return "U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")" end
--- function utilities.strings.chruni(s) return utfchar(s) .. " (U+" .. format("%05X",s) .. ")" end
---
--- utilities.strings.formatters.add (
--- string.formatters, "unichr",
--- [[unichr(%s)]],
--- [[local unichr = utilities.strings.unichr]]
--- )
---
--- utilities.strings.formatters.add (
--- string.formatters, "chruni",
--- [[chruni(%s)]],
--- [[local chruni = utilities.strings.chruni]]
--- )
-
formatters.add (
formatters, "unichr",
[["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
@@ -80,26 +54,6 @@ formatters.add (
[[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
)
--- function utilities.strings.unichk(s) return s <= 0xFFFF and ("U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")") or ("U+" .. format("%05X",s)) end
--- function utilities.strings.chkuni(s) return s <= 0xFFFF and (utfchar(s) .. " (U+" .. format("%05X",s) .. ")") or ("U+" .. format("%05X",s)) end
---
--- utilities.strings.formatters.add (
--- string.formatters, "unichk",
--- [[unichk(%s)]],
--- [[local unichk = utilities.strings.unichk]]
--- )
---
--- utilities.strings.formatters.add (
--- string.formatters, "chkuni",
--- [[chkuni(%s)]],
--- [[local chkuni = utilities.strings.chkuni]]
--- )
---
--- print(formatters["Missing character %!chruni! in font."](234))
--- print(formatters["Missing character %!unichr! in font."](234))
--- print(formatters["Missing character %!chkuni! in font."](234))
--- print(formatters["Missing character %!unichk! in font."](234))
-
-- basic loggers
local function ignore() end
@@ -124,322 +78,7 @@ local function ansisupported(specification)
end
end
-if runningtex and texio then
-
- if texio.setescape then
- texio.setescape(0) -- or (false)
- end
-
- if arg and ansisupported then
- -- we're don't have environment.arguments yet
- for k, v in next, arg do -- k can be negative !
- if v == "--ansi" or v == "--c:ansi" then
- if ansisupported("ansi") then
- variant = "ansi"
- end
- break
- elseif v == "--ansilog" or v == "--c:ansilog" then
- if ansisupported("ansilog") then
- variant = "ansilog"
- end
- break
- end
- end
- end
-
- local function useluawrites()
-
- -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2)
- -- still needed for luajittex .. luatex should not have that ^^ mess
-
- local texio_write_nl = texio.write_nl
- local texio_write = texio.write
- local io_write = io.write
-
- write_nl = function(target,...)
- if not io_write then
- io_write = io.write
- end
- if target == "term and log" then
- texio_write_nl("log",...)
- texio_write_nl("term","")
- io_write(...)
- elseif target == "log" then
- texio_write_nl("log",...)
- elseif target == "term" then
- texio_write_nl("term","")
- io_write(...)
- elseif type(target) == "number" then
- texio_write_nl(target,...) -- a tex output channel
- elseif target ~= "none" then
- texio_write_nl("log",target,...)
- texio_write_nl("term","")
- io_write(target,...)
- end
- end
-
- write = function(target,...)
- if not io_write then
- io_write = io.write
- end
- if target == "term and log" then
- texio_write("log",...)
- io_write(...)
- elseif target == "log" then
- texio_write("log",...)
- elseif target == "term" then
- io_write(...)
- elseif type(target) == "number" then
- texio_write(target,...) -- a tex output channel
- elseif target ~= "none" then
- texio_write("log",target,...)
- io_write(target,...)
- end
- end
-
- texio.write = write
- texio.write_nl = write_nl
-
- useluawrites = ignore
-
- end
-
- -- local format = string.formatter
-
- local whereto = "both"
- local target = nil
- local targets = nil
-
- local formats = table.setmetatableindex("self")
- local translations = table.setmetatableindex("self")
-
- local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes
- local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop
-
- local variants = {
- default = {
- formats = {
- report_yes = formatters["%-15s > %s\n"],
- report_nop = formatters["%-15s >\n"],
- direct_yes = formatters["%-15s > %s"],
- direct_nop = formatters["%-15s >"],
- subreport_yes = formatters["%-15s > %s > %s\n"],
- subreport_nop = formatters["%-15s > %s >\n"],
- subdirect_yes = formatters["%-15s > %s > %s"],
- subdirect_nop = formatters["%-15s > %s >"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- },
- targets = {
- logfile = "log",
- log = "log",
- file = "log",
- console = "term",
- terminal = "term",
- both = "term and log",
- },
- },
- ansi = {
- formats = {
- report_yes = formatters["%-15s > %s\n"],
- report_nop = formatters["%-15s >\n"],
- direct_yes = formatters["%-15s > %s"],
- direct_nop = formatters["%-15s >"],
- subreport_yes = formatters["%-15s > %s > %s\n"],
- subreport_nop = formatters["%-15s > %s >\n"],
- subdirect_yes = formatters["%-15s > %s > %s"],
- subdirect_nop = formatters["%-15s > %s >"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- },
- targets = {
- logfile = "none",
- log = "none",
- file = "none",
- console = "term",
- terminal = "term",
- both = "term",
- },
- }
- }
-
- variants.ansilog = {
- formats = variants.ansi.formats,
- targets = variants.default.targets,
- }
-
- logs.flush = io.flush
-
- writer = function(...)
- write_nl(target,...)
- end
-
- newline = function()
- write_nl(target,"\n")
- end
-
- report = function(a,b,c,...)
- if c ~= nil then
- write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,report_yes(translations[a],formats[b]))
- elseif a then
- write_nl(target,report_nop(translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- direct = function(a,b,c,...)
- if c ~= nil then
- return direct_yes(translations[a],formatters[formats[b]](c,...))
- elseif b then
- return direct_yes(translations[a],formats[b])
- elseif a then
- return direct_nop(translations[a])
- else
- return ""
- end
- end
-
- subreport = function(a,s,b,c,...)
- if c ~= nil then
- write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
- elseif a then
- write_nl(target,subreport_nop(translations[a],translations[s]))
- else
- write_nl(target,"\n")
- end
- end
-
- subdirect = function(a,s,b,c,...)
- if c ~= nil then
- return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
- elseif b then
- return subdirect_yes(translations[a],translations[s],formats[b])
- elseif a then
- return subdirect_nop(translations[a],translations[s])
- else
- return ""
- end
- end
-
- status = function(a,b,c,...)
- if c ~= nil then
- write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,status_yes(translations[a],formats[b]))
- elseif a then
- write_nl(target,status_nop(translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- settarget = function(askedwhereto)
- whereto = askedwhereto or whereto or "both"
- target = targets[whereto]
- if not target then
- whereto = "both"
- target = targets[whereto]
- end
- if target == "term" or target == "term and log" then
- logs.flush = io.flush
- else
- logs.flush = ignore
- end
- end
-
- local stack = { }
-
- pushtarget = function(newtarget)
- insert(stack,target)
- settarget(newtarget)
- end
-
- poptarget = function()
- if #stack > 0 then
- settarget(remove(stack))
- end
- end
-
- setformats = function(f)
- formats = f
- end
-
- settranslations = function(t)
- translations = t
- end
-
- setprocessor = function(f)
- local writeline = write_nl
- write_nl = function(target,...)
- writeline(target,f(...))
- end
- end
-
- setformatters = function(specification)
- local t = nil
- local f = nil
- local d = variants.default
- if not specification then
- --
- elseif type(specification) == "table" then
- t = specification.targets
- f = specification.formats or specification
- else
- if not ansisupported(specification) then
- specification = "default"
- end
- local v = variants[specification]
- if v then
- t = v.targets
- f = v.formats
- variant = specification
- end
- end
- targets = t or d.targets
- target = targets[whereto] or target
- if f then
- d = d.formats
- else
- f = d.formats
- d = f
- end
- setmetatableindex(f,d)
- report_yes = f.report_yes
- report_nop = f.report_nop
- subreport_yes = f.subreport_yes
- subreport_nop = f.subreport_nop
- direct_yes = f.direct_yes
- direct_nop = f.direct_nop
- subdirect_yes = f.subdirect_yes
- subdirect_nop = f.subdirect_nop
- status_yes = f.status_yes
- status_nop = f.status_nop
- if variant == "ansi" or variant == "ansilog" then
- useluawrites() -- because tex escapes ^^, not needed in lmtx
- end
- settarget(whereto)
- end
-
- setformatters(variant)
-
- setlogfile = ignore
- settimedlog = ignore
-
- -- settimedlog = function()
- -- local localtime = os.localtime
- -- local writeline = write_nl
- -- write_nl = function(f,...)
- -- writeline(f,localtime() .. " | " .. concat { ... })
- -- end
- -- settimedlog = ignore
- -- end
-
-else
+do
local report_yes, subreport_yes, status_yes
local report_nop, subreport_nop, status_nop
@@ -788,80 +427,6 @@ directives.register("logs.target", function(v)
settarget(v)
end)
--- tex specific loggers (might move elsewhere)
-
-if tex then
-
- local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
- local texgetcount = tex and tex.getcount
-
- local real, user, sub = 0, 0, 0
-
- function logs.start_page_number()
- real = texgetcount("realpageno")
- user = texgetcount("userpageno")
- sub = texgetcount("subpageno")
- end
-
- local timing = false
- local usage = false
- local lasttime = nil
-
- logs.private = {
- enablepagetiming = function()
- usage = true
- end,
- getpagetiming = function()
- return type(usage) == "table" and usage
- end,
- }
-
- trackers.register("pages.timing", function() timing = "" end)
-
- function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
- if timing or usage then
- local elapsed = statistics.currenttime(statistics)
- local average, page
- if not lasttime or real < 2 then
- average = elapsed
- page = elapsed
- else
- average = elapsed / (real - 1)
- page = elapsed - lasttime
- end
- lasttime = elapsed
- if timing then
- timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
- end
- if usage then
- usage = {
- page = {
- real = real,
- user = user,
- sub = sub,
- },
- time = {
- elapsed = elapsed,
- page = page,
- average = average,
- }
- }
- end
- end
- if real <= 0 then
- report("flushing page%s",timing)
- elseif user <= 0 then
- report("flushing realpage %s%s",real,timing)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s%s",real,user,timing)
- else
- report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
- end
- logs.flush()
- end
-
-end
-
-- we don't have show_open and show_close callbacks yet
----- report_files = logs.reporter("files")
@@ -888,14 +453,6 @@ logs.help = ignore -- obsolete
-- applications
--- local function reportlines(t,str)
--- if str then
--- for line in gmatch(str,"([^\n\r]*)[\n\r]") do
--- t.report(line)
--- end
--- end
--- end
-
local Carg, C, lpegmatch = lpeg.Carg, lpeg.C, lpeg.match
local p_newline = lpeg.patterns.newline
@@ -950,12 +507,12 @@ local function reportexport(t,method)
end
local reporters = {
- lines = reportlines, -- not to be overloaded
- banner = reportbanner,
- version = reportversion,
- help = reporthelp,
- info = reportinfo,
- export = reportexport,
+ lines = reportlines, -- not to be overloaded
+ banner = reportbanner,
+ version = reportversion,
+ help = reporthelp,
+ info = reportinfo,
+ export = reportexport,
}
local exporters = {
@@ -1024,47 +581,10 @@ end
local report_system = logs.reporter("system","logs")
-function logs.obsolete(old,new)
- local o = loadstring("return " .. new)()
- if type(o) == "function" then
- return function(...)
- report_system("function %a is obsolete, use %a",old,new)
- loadstring(old .. "=" .. new .. " return ".. old)()(...)
- end
- elseif type(o) == "table" then
- local t, m = { }, { }
- m.__index = function(t,k)
- report_system("table %a is obsolete, use %a",old,new)
- m.__index, m.__newindex = o, o
- return o[k]
- end
- m.__newindex = function(t,k,v)
- report_system("table %a is obsolete, use %a",old,new)
- m.__index, m.__newindex = o, o
- o[k] = v
- end
- if libraries then
- libraries.obsolete[old] = t -- true
- end
- setmetatable(t,m)
- return t
- end
-end
-
if utilities then
utilities.report = report_system
end
-do
- local texerror = tex and tex.error or print
- local formatters = string.formatters
-
- function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here
- texerror(first and formatters[fmt](first,...) or fmt)
- end
-
-end
-
-- this is somewhat slower but prevents out-of-order messages when print is mixed
-- with texio.write
@@ -1077,104 +597,3 @@ end
if package.helpers.report then
package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun
end
-
-if tex then
-
- local finalactions = { }
- local fatalerrors = { }
- local possiblefatal = { }
- local loggingerrors = false
-
- function logs.loggingerrors()
- return loggingerrors
- end
-
- directives.register("logs.errors",function(v)
- loggingerrors = v
- if type(v) == "string" then
- fatalerrors = settings_to_hash(v)
- else
- fatalerrors = { }
- end
- end)
-
- function logs.registerfinalactions(...)
- insert(finalactions,...) -- so we can force an order if needed
- end
-
- local what = nil
- local report = nil
- local state = nil
- local target = nil
-
- local function startlogging(t,r,w,s)
- target = t
- state = force
- force = true
- report = type(r) == "function" and r or logs.reporter(r)
- what = w
- pushtarget(target)
- newline()
- if s then
- report("start %s: %s",what,s)
- else
- report("start %s",what)
- end
- if target == "logfile" then
- newline()
- end
- return report
- end
-
- local function stoplogging()
- if target == "logfile" then
- newline()
- end
- report("stop %s",what)
- if target == "logfile" then
- newline()
- end
- poptarget()
- state = oldstate
- end
-
- function logs.startfilelogging(...)
- return startlogging("logfile", ...)
- end
-
- logs.stopfilelogging = stoplogging
-
- local done = false
-
- function logs.starterrorlogging(r,w,...)
- if not done then
- pushtarget("terminal")
- newline()
- logs.report("error logging","start possible issues")
- poptarget()
- done = true
- end
- if fatalerrors[w] then
- possiblefatal[w] = true
- end
- return startlogging("terminal",r,w,...)
- end
-
- logs.stoperrorlogging = stoplogging
-
- function logs.finalactions()
- if #finalactions > 0 then
- for i=1,#finalactions do
- finalactions[i]()
- end
- if done then
- pushtarget("terminal")
- newline()
- logs.report("error logging","stop possible issues")
- poptarget()
- end
- return next(possiblefatal) and sortedkeys(possiblefatal) or false
- end
- end
-
-end
diff --git a/tex/context/base/mkiv/trac-vis.lmt b/tex/context/base/mkiv/trac-vis.lmt
new file mode 100644
index 000000000..7ac5964da
--- /dev/null
+++ b/tex/context/base/mkiv/trac-vis.lmt
@@ -0,0 +1,1700 @@
+if not modules then modules = { } end modules ['trac-vis'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to trac-vis.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local node, nodes, attributes, tex = node, nodes, attributes, tex
+local type, tonumber, next, rawget = type, tonumber, next, rawget
+local gmatch = string.gmatch
+local formatters = string.formatters
+local round = math.round
+
+-- This module started out in the early days of mkiv and luatex with visualizing
+-- kerns related to fonts. In the process of cleaning up the visual debugger code it
+-- made sense to integrate some other code that I had laying around and replace the
+-- old supp-vis debugging code. As only a subset of the old visual debugger makes
+-- sense it has become a different implementation. Soms of the m-visual
+-- functionality will also be ported. The code is rather trivial. The caching is not
+-- really needed but saves upto 50% of the time needed to add visualization. Of
+-- course the overall runtime is larger because of color and layer processing in the
+-- backend (can be times as much) so the runtime is somewhat larger with full
+-- visualization enabled. In practice this will never happen unless one is demoing.
+
+-- todo: global switch (so no attributes)
+-- todo: maybe also xoffset, yoffset of glyph
+-- todo: inline concat (more efficient)
+-- todo: tags can also be numbers (just add to hash)
+-- todo: make a lmtx variant (a few more efficient fetchers)
+
+local nodecodes = nodes.nodecodes
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local setboth = nuts.setboth
+local setlink = nuts.setlink
+local setdisc = nuts.setdisc
+local setlist = nuts.setlist
+local setleader = nuts.setleader
+local setsubtype = nuts.setsubtype
+local setattr = nuts.setattr
+local setwidth = nuts.setwidth
+local setshift = nuts.setshift
+
+local getid = nuts.getid
+local getfont = nuts.getfont
+local getattr = nuts.getattr
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local getlist = nuts.getlist
+local getleader = nuts.getleader
+local getnext = nuts.getnext
+local getboth = nuts.getboth
+local getdisc = nuts.getdisc
+local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
+local getdepth = nuts.getdepth
+local getshift = nuts.getshift
+local getexpansion = nuts.getexpansion
+local getdirection = nuts.getdirection
+local getstate = nuts.getstate
+
+local isglyph = nuts.isglyph
+
+local hpack_nodes = nuts.hpack
+local vpack_nodes = nuts.vpack
+local copy_list = nuts.copy_list
+local copy_node = nuts.copy_node
+local flush_node_list = nuts.flush_list
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local apply_to_nodes = nuts.apply
+local effectiveglue = nuts.effective_glue
+
+local hpack_string = nuts.typesetters.tohpack
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+
+local setmetatableindex = table.setmetatableindex
+
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local fonthashes = fonts.hashes
+local chardata = fonthashes.characters
+local exheights = fonthashes.exheights
+local emwidths = fonthashes.emwidths
+local pt_factor = number.dimenfactors.pt
+
+local nodepool = nuts.pool
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+
+local tracers = nodes.tracers
+local visualizers = nodes.visualizers
+
+local setcolor = tracers.colors.set
+local setlistcolor = tracers.colors.setlist
+local settransparency = tracers.transparencies.set
+local setlisttransparency = tracers.transparencies.setlist
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local a_visual = attributes.private("visual")
+local a_layer = attributes.private("viewerlayer")
+
+local band = bit32.band
+local bor = bit32.bor
+
+local enableaction = nodes.tasks.enableaction
+
+-- local trace_hbox
+-- local trace_vbox
+-- local trace_vtop
+-- local trace_kern
+-- local trace_glue
+-- local trace_penalty
+-- local trace_fontkern
+-- local trace_strut
+-- local trace_whatsit
+-- local trace_user
+-- local trace_math
+-- local trace_italic
+-- local trace_discretionary
+-- local trace_expansion
+-- local trace_line
+-- local trace_space
+
+local report_visualize = logs.reporter("visualize")
+
+local modes = {
+ hbox = 0x000001,
+ vbox = 0x000002,
+ vtop = 0x000004,
+ kern = 0x000008,
+ glue = 0x000010,
+ penalty = 0x000020,
+ fontkern = 0x000040,
+ strut = 0x000080,
+ whatsit = 0x000100,
+ glyph = 0x000200,
+ simple = 0x000400,
+ simplehbox = 0x000401,
+ simplevbox = 0x000402,
+ simplevtop = 0x000404,
+ user = 0x000800,
+ math = 0x001000,
+ italic = 0x002000,
+ origin = 0x004000,
+ discretionary = 0x008000,
+ expansion = 0x010000,
+ line = 0x020000,
+ space = 0x040000,
+ depth = 0x080000,
+ marginkern = 0x100000,
+ mathlistkern = 0x200000,
+ dir = 0x400000,
+ par = 0x800000,
+}
+
+local usedfont, exheight, emwidth
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_marginkern, l_mathlistkern, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth,
+ l_dir, l_whatsit
+
+local enabled = false
+local layers = { }
+
+local preset_boxes = modes.hbox + modes.vbox + modes.vtop + modes.origin
+local preset_makeup = preset_boxes
+ + modes.kern + modes.glue + modes.penalty
+local preset_all = preset_makeup
+ + modes.fontkern + modes.marginkern + modes.mathlistkern
+ + modes.whatsit + modes.glyph + modes.user + modes.math
+ + modes.dir + modes.whatsit
+
+function visualizers.setfont(id)
+ usedfont = id or current_font()
+ exheight = exheights[usedfont]
+ emwidth = emwidths[usedfont]
+end
+
+-- we can preset a bunch of bits
+
+local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
+local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
+
+local function initialize()
+ --
+ if not usedfont then
+ -- we use a narrow monospaced font -- infofont ?
+ visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") })
+ end
+ --
+ for mode, value in next, modes do
+ local tag = formatters["v_%s"](mode)
+ attributes.viewerlayers.define {
+ tag = tag,
+ title = formatters["visualizer %s"](mode),
+ visible = "start",
+ editable = "yes",
+ printable = "yes"
+ }
+ layers[mode] = attributes.viewerlayers.register(tag,true)
+ end
+ l_hbox = layers.hbox
+ l_vbox = layers.vbox
+ l_vtop = layers.vtop
+ l_glue = layers.glue
+ l_kern = layers.kern
+ l_penalty = layers.penalty
+ l_fontkern = layers.fontkern
+ l_strut = layers.strut
+ l_whatsit = layers.whatsit
+ l_glyph = layers.glyph
+ l_user = layers.user
+ l_math = layers.math
+ l_italic = layers.italic
+ l_marginkern = layers.marginkern
+ l_mathlistkern = layers.mathlistkern
+ l_origin = layers.origin
+ l_discretionary = layers.discretionary
+ l_expansion = layers.expansion
+ l_line = layers.line
+ l_space = layers.space
+ l_depth = layers.depth
+ l_dir = layers.dir
+ l_par = layers.par
+ --
+ if not userrule then
+ userrule = nuts.rules.userrule
+ end
+ --
+ if not outlinerule then
+ outlinerule = nuts.pool.outlinerule
+ end
+ initialize = false
+end
+
+local function enable()
+ if initialize then
+ initialize()
+ end
+ enableaction("shipouts","nodes.visualizers.handler")
+ report_visualize("enabled")
+ enabled = true
+ tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end
+end
+
+local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in
+ if not n or n == "reset" then
+ return unsetvalue
+ elseif n == true or n == "makeup" then
+ if not a or a == 0 or a == unsetvalue then
+ a = preset_makeup
+ else
+ a = bor(a,preset_makeup)
+ end
+ elseif n == "boxes" then
+ if not a or a == 0 or a == unsetvalue then
+ a = preset_boxes
+ else
+ a = bor(a,preset_boxes)
+ end
+ elseif n == "all" then
+ if what == false then
+ return unsetvalue
+ elseif not a or a == 0 or a == unsetvalue then
+ a = preset_all
+ else
+ a = bor(a,preset_all)
+ end
+ else
+ for s in gmatch(n,"[a-z]+") do
+ local m = modes[s]
+ if not m then
+ -- go on
+ elseif not a or a == 0 or a == unsetvalue then
+ a = m
+ else
+ a = bor(a,m)
+ end
+ end
+ end
+ if not a or a == 0 or a == unsetvalue then
+ return unsetvalue
+ elseif not enabled then -- must happen at runtime (as we don't store layers yet)
+ enable()
+ end
+ return a
+end
+
+function nuts.setvisual(n,mode)
+ setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true))
+end
+
+function nuts.setvisuals(n,mode) -- currently the same
+ setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true,true))
+end
+
+-- fast setters
+
+do
+
+ local cached = setmetatableindex(function(t,k)
+ if k == true then
+ return texgetattribute(a_visual)
+ elseif not k then
+ t[k] = unsetvalue
+ return unsetvalue
+ else
+ local v = setvisual(k)
+ t[k] = v
+ return v
+ end
+ end)
+
+ -- local function applyvisuals(n,mode)
+ -- local a = cached[mode]
+ -- apply_to_nodes(n,function(n) setattr(n,a_visual,a) end)
+ -- end
+
+ local a = unsetvalue
+
+ local f = function(n) setattr(n,a_visual,a) end
+
+ local function applyvisuals(n,mode)
+ a = cached[mode]
+ apply_to_nodes(n,f)
+ end
+
+ nuts.applyvisuals = applyvisuals
+
+ function nodes.applyvisuals(n,mode)
+ applyvisuals(tonut(n),mode)
+ end
+
+ function visualizers.attribute(mode)
+ return cached[mode]
+ end
+
+ visualizers.attributes = cached
+
+end
+
+function nuts.copyvisual(n,m)
+ setattr(n,a_visual,getattr(m,a_visual))
+end
+
+function visualizers.setvisual(n)
+ texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual)))
+end
+
+function visualizers.setlayer(n)
+ texsetattribute(a_layer,layers[n] or unsetvalue)
+end
+
+local function set(mode,v)
+ texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v))
+end
+
+for mode, value in next, modes do
+ trackers.register(formatters["visualizers.%s"](mode), function(v) set(mode,v) end)
+end
+
+local fraction = 10
+
+trackers .register("visualizers.reset", function(v) set("reset", v) end)
+trackers .register("visualizers.all", function(v) set("all", v) end)
+trackers .register("visualizers.makeup", function(v) set("makeup",v) end)
+trackers .register("visualizers.boxes", function(v) set("boxes", v) end)
+directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end)
+
+local c_positive = "trace:b"
+local c_negative = "trace:r"
+local c_zero = "trace:g"
+local c_text = "trace:s"
+local c_space = "trace:y"
+local c_space_x = "trace:m"
+local c_skip_a = "trace:c"
+local c_skip_b = "trace:m"
+local c_glyph = "trace:o"
+local c_ligature = "trace:s"
+local c_white = "trace:w"
+----- c_math = "trace:s"
+----- c_origin = "trace:o"
+----- c_discretionary = "trace:d"
+----- c_expansion = "trace:o"
+local c_depth = "trace:o"
+local c_indent = "trace:s"
+
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+local c_zero_d = "trace:dg"
+local c_text_d = "trace:ds"
+local c_space_d = "trace:dy"
+local c_space_x_d = "trace:dm"
+local c_skip_a_d = "trace:dc"
+local c_skip_b_d = "trace:dm"
+local c_glyph_d = "trace:do"
+local c_ligature_d = "trace:ds"
+local c_white_d = "trace:dw"
+local c_math_d = "trace:dr"
+local c_origin_d = "trace:do"
+local c_discretionary_d = "trace:dd"
+----- c_expansion_d = "trace:do"
+----- c_depth_d = "trace:do"
+----- c_indent_d = "trace:ds"
+
+local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
+ local text = hpack_string(str,usedfont)
+ local size = getwidth(text)
+ local rule = new_rule(size,2*exheight,exheight/2)
+ local kern = new_kern(-size)
+ if color then
+ setcolor(rule,color)
+ end
+ if textcolor then
+ setlistcolor(getlist(text),textcolor)
+ end
+ local info = setlink(rule,kern,text)
+ setlisttransparency(info,c_zero)
+ info = hpack_nodes(info)
+ local width = getwidth(info)
+ if lap then
+ info = new_hlist(setlink(new_kern(-width),info))
+ else
+ info = new_hlist(info) -- a bit overkill: double wrapped
+ end
+ if layer then
+ setattr(info,a_layer,layer)
+ end
+ return info, width
+end
+
+local function someblob(str,layer,color,textcolor,width)
+ local text = hpack_string(str,usedfont)
+ local size = getwidth(text)
+ local rule = new_rule(width,2*exheight,exheight/2)
+ local kern = new_kern(-width + (width-size)/2)
+ if color then
+ setcolor(rule,color)
+ end
+ if textcolor then
+ setlistcolor(getlist(text),textcolor)
+ end
+ local info = setlink(rule,kern,text)
+ setlisttransparency(info,c_zero)
+ info = hpack_nodes(info)
+ local width = getwidth(info)
+ info = new_hlist(info)
+ if layer then
+ setattr(info,a_layer,layer)
+ end
+ return info, width
+end
+
+local caches = setmetatableindex("table")
+
+local fontkern, italickern, marginkern, mathlistkern do
+
+ local f_cache = caches["fontkern"]
+ local i_cache = caches["italickern"]
+ local m_cache = caches["marginkern"]
+ local l_cache = caches["mathlistkern"]
+
+ local function somekern(head,current,cache,color,layer)
+ local width = getkern(current)
+ local extra = getexpansion(current)
+ local kern = width + extra
+ local info = cache[kern]
+ if not info then
+ local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
+ local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
+ local list = getlist(text)
+ if kern > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif kern < 0 then
+ setlistcolor(list,c_negative_d)
+ else
+ setlistcolor(list,c_zero_d)
+ end
+ setlisttransparency(list,color)
+ setcolor(rule,color)
+ settransparency(rule,color)
+ setshift(text,-5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,layer)
+ f_cache[kern] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+ end
+
+ fontkern = function(head,current)
+ return somekern(head,current,f_cache,c_text_d,l_fontkern)
+ end
+
+ italickern = function(head,current)
+ return somekern(head,current,i_cache,c_glyph_d,l_italic)
+ end
+
+ marginkern = function(head,current)
+ return somekern(head,current,m_cache,c_glyph_d,l_marginkern)
+ end
+
+ mathlistkern = function(head,current)
+ return somekern(head,current,l_cache,c_glyph_d,l_mathlistkern)
+ end
+
+end
+
+local glyphexpansion do
+
+ local f_cache = caches["glyphexpansion"]
+
+ glyphexpansion = function(head,current)
+ local extra = getexpansion(current)
+ if extra and extra ~= 0 then
+ extra = extra / 1000
+ local info = f_cache[extra]
+ if not info then
+ local text = hpack_string(round(extra),usedfont)
+ local rule = new_rule(emwidth/fraction,exheight,2*exheight)
+ local list = getlist(text)
+ if extra > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif extra < 0 then
+ setlistcolor(list,c_negative_d)
+ end
+ setlisttransparency(list,c_text_d)
+ setcolor(rule,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,1.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_expansion)
+ f_cache[extra] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+ end
+ return head, current
+ end
+
+end
+
+local kernexpansion do
+
+ local f_cache = caches["kernexpansion"]
+
+ -- in mkiv we actually need to reconstruct but let's not do that now
+
+ kernexpansion = function(head,current)
+ local extra = getexpansion(current)
+ if extra ~= 0 then
+ extra = extra / 1000
+ local info = f_cache[extra]
+ if not info then
+ local text = hpack_string(round(extra),usedfont)
+ local rule = new_rule(emwidth/fraction,exheight,4*exheight)
+ local list = getlist(text)
+ if extra > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif extra < 0 then
+ setlistcolor(list,c_negative_d)
+ end
+ setlisttransparency(list,c_text_d)
+ setcolor(rule,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,3.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_expansion)
+ f_cache[extra] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+ end
+ return head, current
+ end
+
+end
+
+local whatsit do
+
+ local whatsitcodes = nodes.whatsitcodes
+ local w_cache = caches["whatsit"]
+
+ local tags = {
+ open = "OPN",
+ write = "WRI",
+ close = "CLS",
+ special = "SPE",
+ latelua = "LUA",
+ savepos = "POS",
+ userdefined = "USR",
+ literal = "LIT",
+ setmatrix = "MAT",
+ save = "SAV",
+ restore = "RES",
+ }
+
+ whatsit = function(head,current)
+ local what = getsubtype(current)
+ local info = w_cache[what]
+ if info then
+ -- print("hit whatsit")
+ else
+ info = sometext(formatters["W:%s"](what),usedfont,nil,c_white)
+ setattr(info,a_layer,l_whatsit)
+ w_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+ end
+
+end
+
+local dir, par do
+
+ local dircodes = nodes.dircodes
+ local dirvalues = nodes.dirvalues
+
+ local cancel_code = dircodes.cancel
+ local l2r_code = dirvalues.l2r
+ local r2l_code = dirvalues.r2l
+
+ local d_cache = caches["dir"]
+
+ local tags = {
+ l2r = "L2R",
+ r2l = "R2L",
+ cancel = "CAN",
+ par = "PAR",
+ }
+
+ par = function(head,current)
+ local what = "par" -- getsubtype(current)
+ local info = d_cache[what]
+ if info then
+ -- print("hit par")
+ else
+ info = sometext(formatters["L:%s"](what),usedfont,nil,c_white)
+ setattr(info,a_layer,l_dir)
+ d_cache[what] = info
+ end
+ return head, current
+ end
+
+ dir = function(head,current)
+ local what = getsubtype(current)
+ if what == cancelcode then
+ what = "cancel"
+ elseif getdirection(current) == r2l_code then
+ what = "r2l"
+ else
+ what = "l2r"
+ end
+ local info = d_cache[what]
+ if info then
+ -- print("hit dir")
+ else
+ info = sometext(formatters["D:%s"](what),usedfont,nil,c_white)
+ setattr(info,a_layer,l_dir)
+ d_cache[what] = info
+ end
+ return head, current
+ end
+
+end
+
+local user do
+
+ local u_cache = caches["user"]
+
+ user = function(head,current)
+ local what = getsubtype(current)
+ local info = u_cache[what]
+ if info then
+ -- print("hit user")
+ else
+ info = sometext(formatters["U:%s"](what),usedfont)
+ setattr(info,a_layer,l_user)
+ u_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+ end
+
+end
+
+local math do
+
+ local mathcodes = nodes.mathcodes
+ local m_cache = {
+ beginmath = caches["bmath"],
+ endmath = caches["emath"],
+ }
+ local tags = {
+ beginmath = "B",
+ endmath = "E",
+ }
+
+ math = function(head,current)
+ local what = getsubtype(current)
+ local tag = mathcodes[what]
+ local skip = getkern(current) + getwidth(current) -- surround
+ local info = m_cache[tag][skip]
+ if info then
+ -- print("hit math")
+ else
+ local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
+ local rule = new_rule(skip,-655360/fraction,2*655360/fraction)
+ setcolor(rule,c_math_d)
+ settransparency(rule,c_math_d)
+ setattr(rule,a_layer,l_math)
+ if tag == "beginmath" then
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text))
+ else
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text))
+ end
+ setattr(info,a_layer,l_math)
+ m_cache[tag][skip] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
+ end
+
+end
+
+local ruleddepth do
+
+ ruleddepth = function(current,wd,ht,dp)
+ local wd, ht, dp = getwhd(current)
+ if dp ~= 0 then
+ local rule = new_rule(wd,0,dp)
+ setcolor(rule,c_depth)
+ settransparency(rule,c_zero)
+ setattr(rule,a_layer,l_depth)
+ setlist(current,setlink(rule,new_kern(-wd),getlist(current)))
+ end
+ end
+
+end
+
+local ruledbox do
+
+ local b_cache = caches["box"]
+ local o_cache = caches["origin"]
+
+ setmetatableindex(o_cache,function(t,size)
+ local rule = new_rule(2*size,size,size)
+ local origin = hpack_nodes(rule)
+ setcolor(rule,c_origin_d)
+ settransparency(rule,c_origin_d)
+ setattr(rule,a_layer,l_origin)
+ t[size] = origin
+ return origin
+ end)
+
+ ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
+ local wd, ht, dp = getwhd(current)
+ if wd ~= 0 then
+ local shift = getshift(current)
+ local next = getnext(current)
+ local prev = previous
+ setboth(current)
+ local linewidth = emwidth/fraction
+ local size = 2*linewidth
+ local this
+ if not simple then
+ this = b_cache[what]
+ if not this then
+ local text = hpack_string(what,usedfont)
+ this = setlink(new_kern(-getwidth(text)),text)
+ setlisttransparency(this,c_text)
+ this = new_hlist(this)
+ b_cache[what] = this
+ end
+ end
+ -- we need to trigger the right mode (else sometimes no whatits)
+ local info = setlink(
+ this and copy_list(this) or nil,
+ (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
+ width = wd,
+ height = ht,
+ depth = dp,
+ line = linewidth,
+ type = "box",
+ dashed = 3*size,
+ }
+ )
+ --
+ setlisttransparency(info,c_text)
+ info = new_hlist(info) -- important
+ --
+ setattr(info,a_layer,layer)
+ if vertical then
+ if shift == 0 then
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info)
+ else
+ -- todo .. i need an example
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ end
+ setshift(current,0)
+ else
+ info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info)
+ setshift(current,0)
+ end
+ info = new_vlist(info,wd,ht,dp,shift)
+ else
+ if shift == 0 then
+ info = setlink(current,new_kern(-wd),info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ else
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ end
+ setshift(current,0)
+ else
+ info = setlink(current,new_kern(-wd),info)
+ setshift(current,0)
+ end
+ info = new_hlist(info,wd,ht,dp,shift)
+ end
+ if next then
+ setlink(info,next)
+ end
+ if prev and prev > 0 then
+ setlink(prev,info)
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+ end
+
+end
+
+local ruledglyph do
+
+ -- see boundingbox feature .. maybe a pdf stream is more efficient, after all we
+ -- have a frozen color anyway or i need a more detailed cache .. below is a more
+ -- texie approach
+
+ ruledglyph = function(head,current,previous) -- wrong for vertical glyphs
+ local wd = getwidth(current)
+ if wd ~= 0 then
+ local wd, ht, dp = getwhd(current)
+ local next = getnext(current)
+ local prev = previous
+ setboth(current)
+ local linewidth = emwidth/(2*fraction)
+ local info
+ --
+ info = setlink(
+ (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
+ width = wd,
+ height = ht,
+ depth = dp,
+ line = linewidth,
+ type = "box",
+ },
+ new_kern(-wd)
+ )
+ --
+ local c, f = isglyph(current)
+ local char = chardata[f][c]
+ if char and type(char.unicode) == "table" then -- hackery test
+ setlistcolor(info,c_ligature)
+ setlisttransparency(info,c_ligature_d)
+ else
+ setlistcolor(info,c_glyph)
+ setlisttransparency(info,c_glyph_d)
+ end
+ info = new_hlist(info)
+ setattr(info,a_layer,l_glyph)
+ local info = setlink(current,new_kern(-wd),info)
+ info = hpack_nodes(info)
+ setwidth(info,wd)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
+ setlink(prev,info)
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+ end
+
+ function visualizers.setruledglyph(f)
+ ruledglyph = f or ruledglyph
+ end
+
+end
+
+local ruledglue do
+
+ local gluecodes = nodes.gluecodes
+
+ local userskip_code = gluecodes.userskip
+ local spaceskip_code = gluecodes.spaceskip
+ local xspaceskip_code = gluecodes.xspaceskip
+ local zerospaceskip_code = gluecodes.zerospaceskip or gluecodes.userskip
+ -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip
+ local leftskip_code = gluecodes.leftskip
+ local rightskip_code = gluecodes.rightskip
+ local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code
+ local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code
+ local indentskip_code = gluecodes.indentskip
+ local correctionskip_code = gluecodes.correctionskip
+
+ local g_cache_v = caches["vglue"]
+ local g_cache_h = caches["hglue"]
+
+ local tags = {
+ -- [userskip_code] = "US",
+ [gluecodes.lineskip] = "LI",
+ [gluecodes.baselineskip] = "BS",
+ [gluecodes.parskip] = "PS",
+ [gluecodes.abovedisplayskip] = "DA",
+ [gluecodes.belowdisplayskip] = "DB",
+ [gluecodes.abovedisplayshortskip] = "SA",
+ [gluecodes.belowdisplayshortskip] = "SB",
+ [gluecodes.topskip] = "TS",
+ [gluecodes.splittopskip] = "ST",
+ [gluecodes.tabskip] = "AS",
+ [gluecodes.lefthangskip] = "LH",
+ [gluecodes.righthangskip] = "RH",
+ [gluecodes.thinmuskip] = "MS",
+ [gluecodes.medmuskip] = "MM",
+ [gluecodes.thickmuskip] = "ML",
+ [gluecodes.intermathskip] = "IM",
+ [gluecodes.keepskip or 99] = "KS",
+ [gluecodes.mathskip] = "MT",
+ [gluecodes.leaders] = "NL",
+ [gluecodes.cleaders] = "CL",
+ [gluecodes.xleaders] = "XL",
+ [gluecodes.gleaders] = "GL",
+ -- true = "VS",
+ -- false = "HS",
+ [leftskip_code] = "LS",
+ [rightskip_code] = "RS",
+ [spaceskip_code] = "SP",
+ [xspaceskip_code] = "XS",
+ [zerospaceskip_code] = "ZS",
+ [parfillleftskip_code] = "PL",
+ [parfillrightskip_code] = "PR",
+ [indentskip_code] = "IN",
+ [correctionskip_code] = "CS",
+ }
+
+ -- we sometimes pass previous as we can have issues in math (not watertight for all)
+
+ ruledglue = function(head,current,vertical,parent)
+ local subtype = getsubtype(current)
+ local width = effectiveglue(current,parent)
+ local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
+ local info = (vertical and g_cache_v or g_cache_h)[amount]
+ if info then
+ -- print("glue hit")
+ else
+ if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then
+ 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 == 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
+ if width > 0 then
+ info = sometext(amount,l_glue,c_positive)
+ elseif width < 0 then
+ info = sometext(amount,l_glue,c_negative)
+ else
+ info = sometext(amount,l_glue,c_zero)
+ end
+ else
+ info = sometext(amount,l_glue,c_skip_b)
+ end
+ (vertical and g_cache_v or g_cache_h)[amount] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+ -- ruledspace = function(head,current,parent)
+ -- local subtype = getsubtype(current)
+ -- if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then
+ -- local width = effectiveglue(current,parent)
+ -- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor)
+ -- local info = g_cache_h[amount]
+ -- if info then
+ -- -- print("space hit")
+ -- else
+ -- info = sometext(amount,l_glue,c_space)
+ -- g_cache_h[amount] = info
+ -- end
+ -- info = copy_list(info)
+ -- head, current = insert_node_before(head,current,info)
+ -- return head, getnext(current)
+ -- else
+ -- return head, current
+ -- end
+ -- end
+
+ local g_cache_s = caches["space"]
+ local g_cache_x = caches["xspace"]
+
+ ruledspace = function(head,current,parent)
+ local subtype = getsubtype(current)
+ if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then -- not yet all space
+ local width = effectiveglue(current,parent)
+ local info
+ if subtype == spaceskip_code then
+ info = g_cache_s[width]
+ if not info then
+ info = someblob("SP",l_glue,c_space,nil,width)
+ g_cache_s[width] = info
+ end
+ else
+ info = g_cache_x[width]
+ if not info then
+ info = someblob("XS",l_glue,c_space_x,nil,width)
+ g_cache_x[width] = info
+ end
+ end
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ else
+ return head, current
+ end
+ end
+
+end
+
+local ruledkern do
+
+ local k_cache_v = caches["vkern"]
+ local k_cache_h = caches["hkern"]
+
+ ruledkern = function(head,current,vertical,mk)
+ local kern = getkern(current)
+ local cache = vertical and k_cache_v or k_cache_h
+ local info = cache[kern]
+ if not info then
+ local amount = formatters["%s:%0.3f"](vertical and "VK" or (mk and "MK") or "HK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ cache[kern] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+end
+
+local ruleditalic do
+
+ local i_cache = caches["italic"]
+
+ ruleditalic = function(head,current)
+ local kern = getkern(current)
+ local info = i_cache[kern]
+ if not info then
+ local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ i_cache[kern] = info
+ end
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+end
+
+local ruledmarginkern do
+
+ local m_cache = caches["marginkern"]
+
+ ruledmarginkern = function(head,current)
+ local kern = getkern(current)
+ local info = m_cache[kern]
+ if not info then
+ local amount = formatters["%s:%0.3f"]("MK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_marginkern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_marginkern,c_negative)
+ else
+ info = sometext(amount,l_marginkern,c_zero)
+ end
+ m_cache[kern] = info
+ end
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+end
+
+local ruledmathlistkern do
+
+ local l_cache = caches["mathlistkern"]
+
+ ruledmathlistkern = function(head,current)
+ local kern = getkern(current)
+ local info = l_cache[kern]
+ if not info then
+ local amount = formatters["%s:%0.3f"]("LK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_mathlistkern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_mathlistkern,c_negative)
+ else
+ info = sometext(amount,l_mathlistkern,c_zero)
+ end
+ l_cache[kern] = info
+ end
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+end
+
+local ruleddiscretionary do
+
+ local d_cache = caches["discretionary"]
+
+ ruleddiscretionary = function(head,current)
+ local d = d_cache[true]
+ if not the_discretionary then
+ local rule = new_rule(4*emwidth/fraction,4*exheight,exheight)
+ local kern = new_kern(-2*emwidth/fraction)
+ setlink(kern,rule)
+ setcolor(rule,c_discretionary_d)
+ settransparency(rule,c_discretionary_d)
+ setattr(rule,a_layer,l_discretionary)
+ d = new_hlist(kern)
+ d_cache[true] = d
+ end
+ insert_node_after(head,current,copy_list(d))
+ return head, current
+ end
+
+end
+
+local ruledpenalty do
+
+ local p_cache_v = caches["vpenalty"]
+ local p_cache_h = caches["hpenalty"]
+
+ local raisepenalties = false
+
+ directives.register("visualizers.raisepenalties",function(v) raisepenalties = v end)
+
+ ruledpenalty = function(head,current,vertical)
+ local penalty = getpenalty(current)
+ local info = (vertical and p_cache_v or p_cache_h)[penalty]
+ if info then
+ -- print("penalty hit")
+ else
+ local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
+ if penalty > 0 then
+ info = sometext(amount,l_penalty,c_positive)
+ elseif penalty < 0 then
+ info = sometext(amount,l_penalty,c_negative)
+ else
+ info = sometext(amount,l_penalty,c_zero)
+ end
+ (vertical and p_cache_v or p_cache_h)[penalty] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ elseif raisepenalties then
+ setshift(info,-65536*4)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
+ end
+
+end
+
+do
+
+ local disc_code = nodecodes.disc
+ local kern_code = nodecodes.kern
+ local glyph_code = nodecodes.glyph
+ local glue_code = nodecodes.glue
+ local penalty_code = nodecodes.penalty
+ local whatsit_code = nodecodes.whatsit
+ local user_code = nodecodes.user
+ local math_code = nodecodes.math
+ local hlist_code = nodecodes.hlist
+ local vlist_code = nodecodes.vlist
+ local marginkern_code = nodecodes.marginkern
+ local mathlistkern_code = nodecodes.mathlistkern
+ local dir_code = nodecodes.dir
+ local par_code = nodecodes.par
+
+ local kerncodes = nodes.kerncodes
+ local fontkern_code = kerncodes.fontkern
+ local italickern_code = kerncodes.italiccorrection
+ local leftmarginkern_code = kerncodes.leftmarginkern
+ local rightmarginkern_code = kerncodes.rightmarginkern
+ local mathlistkern_code = kerncodes.mathlistkern
+ ----- userkern_code = kerncodes.userkern
+
+ local listcodes = nodes.listcodes
+ local linelist_code = listcodes.line
+
+ local vtop_package_state = 3 -- todo: symbolic
+
+ local cache
+
+ local function visualize(head,vertical,forced,parent)
+ local trace_hbox = false
+ local trace_vbox = false
+ local trace_vtop = false
+ local trace_kern = false
+ local trace_glue = false
+ local trace_penalty = false
+ local trace_fontkern = false
+ local trace_strut = false
+ local trace_whatsit = false
+ local trace_glyph = false
+ local trace_simple = false
+ local trace_user = false
+ local trace_math = false
+ local trace_italic = false
+ local trace_origin = false
+ local trace_discretionary = false
+ local trace_expansion = false
+ local trace_line = false
+ local trace_space = false
+ local trace_depth = false
+ local trace_dir = false
+ local trace_par = false
+ local current = head
+ local previous = nil
+ local attr = unsetvalue
+ local prev_trace_fontkern = nil
+ local prev_trace_italic = nil
+ local prev_trace_marginkern = nil
+-- local prev_trace_mathlist = nil
+ local prev_trace_expansion = nil
+
+ while current do
+ local id = getid(current)
+ local a = forced or getattr(current,a_visual) or unsetvalue
+ local subtype
+ if a ~= attr then
+ prev_trace_fontkern = trace_fontkern
+ prev_trace_italic = trace_italic
+ prev_trace_marginkern = trace_marginkern
+-- prev_trace_mathlistkern = trace_mathlistkern
+ prev_trace_expansion = trace_expansion
+ attr = a
+ if a == unsetvalue then
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ trace_math = false
+ trace_italic = false
+ trace_origin = false
+ trace_discretionary = false
+ trace_expansion = false
+ trace_line = false
+ trace_space = false
+ trace_depth = false
+ trace_marginkern = false
+ trace_mathlistkern = false
+ trace_dir = false
+ trace_par = false
+ if id == kern_code then
+ goto kern
+ else
+ goto list
+ end
+ else -- dead slow:
+ -- cache[a]()
+ trace_hbox = band(a,0x000001) ~= 0
+ trace_vbox = band(a,0x000002) ~= 0
+ trace_vtop = band(a,0x000004) ~= 0
+ trace_kern = band(a,0x000008) ~= 0
+ trace_glue = band(a,0x000010) ~= 0
+ trace_penalty = band(a,0x000020) ~= 0
+ trace_fontkern = band(a,0x000040) ~= 0
+ trace_strut = band(a,0x000080) ~= 0
+ trace_whatsit = band(a,0x000100) ~= 0
+ trace_glyph = band(a,0x000200) ~= 0
+ trace_simple = band(a,0x000400) ~= 0
+ trace_user = band(a,0x000800) ~= 0
+ trace_math = band(a,0x001000) ~= 0
+ trace_italic = band(a,0x002000) ~= 0
+ trace_origin = band(a,0x004000) ~= 0
+ trace_discretionary = band(a,0x008000) ~= 0
+ trace_expansion = band(a,0x010000) ~= 0
+ trace_line = band(a,0x020000) ~= 0
+ trace_space = band(a,0x040000) ~= 0
+ trace_depth = band(a,0x080000) ~= 0
+ trace_marginkern = band(a,0x100000) ~= 0
+ trace_mathlistkern = band(a,0x200000) ~= 0
+ trace_dir = band(a,0x400000) ~= 0
+ trace_whatsit = band(a,0x800000) ~= 0
+ end
+ elseif a == unsetvalue then
+ goto list
+ end
+ if trace_strut then
+ setattr(current,a_layer,l_strut)
+ elseif id == glyph_code then
+ if trace_glyph then
+ head, current = ruledglyph(head,current,previous)
+ end
+ if trace_expansion then
+ head, current = glyphexpansion(head,current)
+ end
+ elseif id == disc_code then
+ if trace_discretionary then
+ head, current = ruleddiscretionary(head,current)
+ end
+ local pre, post, replace = getdisc(current)
+ if pre then
+ pre = visualize(pre,false,a,parent)
+ end
+ if post then
+ post = visualize(post,false,a,parent)
+ end
+ if replace then
+ replace = visualize(replace,false,a,parent)
+ end
+ setdisc(current,pre,post,replace)
+ elseif id == kern_code then
+ goto kern
+ elseif id == glue_code then
+ local content = getleader(current)
+ if content then
+ setleader(current,visualize(content,false,nil,parent))
+ elseif trace_glue then
+ head, current = ruledglue(head,current,vertical,parent)
+ elseif trace_space then
+ head, current = ruledspace(head,current,parent)
+ end
+ elseif id == penalty_code then
+ if trace_penalty then
+ head, current = ruledpenalty(head,current,vertical)
+ end
+ elseif id == hlist_code or id == vlist_code then
+ goto list
+ elseif id == whatsit_code then
+ if trace_whatsit then
+ head, current = whatsit(head,current)
+ end
+ elseif id == user_code then
+ if trace_user then
+ head, current = user(head,current)
+ end
+ elseif id == math_code then
+ if trace_math then
+ head, current = math(head,current)
+ end
+ elseif id == marginkern_code then
+ if trace_kern then
+ head, current = ruledkern(head,current,vertical,true)
+ end
+ elseif id == dir_code then
+ if trace_dir then
+ head, current = dir(head,current)
+ end
+ elseif id == par_code then
+ if trace_par then
+ head, current = par(head,current)
+ end
+ end
+ goto next
+ ::kern::
+ subtype = getsubtype(current)
+ if subtype == fontkern_code then
+ if trace_fontkern or prev_trace_fontkern then
+ head, current = fontkern(head,current)
+ end
+ if trace_expansion or prev_trace_expansion then
+ head, current = kernexpansion(head,current)
+ end
+ elseif subtype == italickern_code then
+ if trace_italic or prev_trace_italic then
+ head, current = italickern(head,current)
+ elseif trace_kern then
+ head, current = ruleditalic(head,current)
+ end
+ elseif subtype == leftmarginkern_code or subtype == rightmarginkern_code then
+ if trace_marginkern or prev_trace_marginkern then
+ head, current = marginkern(head,current)
+ elseif trace_kern then
+ head, current = ruledmarginkern(head,current)
+ end
+ elseif subtype == mathlistkern_code then
+ if trace_mathlist then -- or prev_trace_mathlist then
+ head, current = mathlistkern(head,current)
+ elseif trace_kern then
+ head, current = ruledmathlistkern(head,current)
+ end
+ else
+ if trace_kern then
+ head, current = ruledkern(head,current,vertical)
+ end
+ end
+ goto next;
+ ::list::
+ if id == hlist_code then
+ local content = getlist(current)
+ if content then
+ setlist(current,visualize(content,false,nil,current))
+ end
+ if trace_depth then
+ ruleddepth(current)
+ end
+ if trace_line and getsubtype(current) == linelist_code then
+ head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent)
+ elseif trace_hbox then
+ head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
+ end
+ elseif id == vlist_code then
+ local content = getlist(current)
+ local isvtop = getstate(current) == vtop_package_state
+ local tag = nil
+ local layer = nil
+ if content then
+ setlist(current,visualize(content,true,nil,current))
+ end
+ if trace_vtop then
+ if isvtop then
+ tag = "_T_"
+ layer = l_vtop
+ elseif trace_vbox then
+ tag = "__V"
+ layer = l_vbox
+ end
+ elseif trace_vbox then
+ if not isvtop then
+ tag = "__V"
+ layer = l_vbox
+ end
+ end
+ if tag then
+ head, current = ruledbox(head,current,true,layer,tag,trace_simple,previous,trace_origin,parent)
+ end
+ end
+ ::next::
+ previous = current
+ current = getnext(current)
+ end
+ return head
+ end
+
+ local function cleanup()
+ for tag, cache in next, caches do
+ for k, v in next, cache do
+ flush_node_list(v)
+ end
+ end
+ cleanup = function()
+ report_visualize("error, duplicate cleanup")
+ end
+ end
+
+ luatex.registerstopactions(cleanup)
+
+ function visualizers.handler(head)
+ if usedfont then
+ starttiming(visualizers)
+ head = visualize(head,true)
+ stoptiming(visualizers)
+ return head, true
+ else
+ return head, false
+ end
+ end
+
+ function visualizers.box(n)
+ if usedfont then
+ starttiming(visualizers)
+ local box = getbox(n)
+ if box then
+ setlist(box,visualize(getlist(box),getid(box) == vlist_code))
+ end
+ stoptiming(visualizers)
+ return head, true
+ else
+ return head, false
+ end
+ end
+
+end
+
+do
+
+ local hlist_code = nodecodes.hlist
+ local vlist_code = nodecodes.vlist
+ local nextnode = nuts.traversers.node
+
+ local last = nil
+ local used = nil
+
+ local mark = {
+ "trace:1", "trace:2", "trace:3",
+ "trace:4", "trace:5", "trace:6",
+ "trace:7",
+ }
+
+ local function markfonts(list)
+ for n, id in nextnode, list do
+ if id == glyph_code then
+ local font = getfont(n)
+ local okay = used[font]
+ if not okay then
+ last = last + 1
+ okay = mark[last]
+ used[font] = okay
+ end
+ setcolor(n,okay)
+ elseif id == hlist_code or id == vlist_code then
+ markfonts(getlist(n))
+ end
+ end
+ end
+
+ function visualizers.markfonts(list)
+ last, used = 0, { }
+ markfonts(type(n) == "number" and getlist(getbox(n)) or n)
+ end
+
+end
+
+statistics.register("visualization time",function()
+ if enabled then
+ -- cleanup() -- in case we don't don't do it each time
+ return formatters["%s seconds"](statistics.elapsedtime(visualizers))
+ end
+end)
+
+-- interface
+
+do
+
+ local implement = interfaces.implement
+
+ implement {
+ name = "setvisual",
+ arguments = "string",
+ actions = visualizers.setvisual
+ }
+
+ implement {
+ name = "setvisuals",
+ arguments = "string",
+ actions = visualizers.setvisual
+ }
+
+ implement {
+ name = "getvisual",
+ arguments = "string",
+ actions = { setvisual, context }
+ }
+
+ implement {
+ name = "setvisuallayer",
+ arguments = "string",
+ actions = visualizers.setlayer
+ }
+
+ implement {
+ name = "markvisualfonts",
+ arguments = "integer",
+ actions = visualizers.markfonts
+ }
+
+ implement {
+ name = "setvisualfont",
+ arguments = "integer",
+ actions = visualizers.setfont
+ }
+
+end
+
+-- Here for now:
+
+do
+
+ local function make(str,forecolor,rulecolor,layer)
+ if initialize then
+ initialize()
+ end
+ local rule = new_rule(emwidth/fraction,exheight,4*exheight)
+ setcolor(rule,rulecolor)
+ settransparency(rule,rulecolor)
+ local info
+ if str == "" then
+ info = new_hlist(rule)
+ else
+ local text = hpack_string(str,usedfont)
+ local list = getlist(text)
+ setlistcolor(list,textcolor)
+ setlisttransparency(list,textcolor)
+ setshift(text,3.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ end
+ setattr(info,a_layer,layer)
+ return info
+ end
+
+ function visualizers.register(name,textcolor,rulecolor)
+ if rawget(layers,name) then
+ -- message
+ return
+ end
+ local cache = caches[name]
+ local layer = layers[name]
+ if not textcolor then
+ textcolor = c_text_d
+ end
+ if not rulecolor then
+ rulecolor = c_origin_d
+ end
+ return function(str)
+ if not str then
+ str = ""
+ end
+ local info = cache[str]
+ if not info then
+ info = make(str,textcolor,rulecolor,layer)
+ cache[str] = info
+ end
+ return copy_node(info)
+ end
+ end
+
+end
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index c676f4dd7..fb5ef98d9 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -28,12 +28,12 @@ local round = math.round
-- todo: maybe also xoffset, yoffset of glyph
-- todo: inline concat (more efficient)
-- todo: tags can also be numbers (just add to hash)
+-- todo: make a lmtx variant (a few more efficient fetchers)
local nodecodes = nodes.nodecodes
local nuts = nodes.nuts
local tonut = nuts.tonut
-local tonode = nuts.tonode
local setboth = nuts.setboth
local setlink = nuts.setlink
@@ -64,6 +64,7 @@ local getdepth = nuts.getdepth
local getshift = nuts.getshift
local getexpansion = nuts.getexpansion
local getdirection = nuts.getdirection
+local getstate = nuts.getstate
local isglyph = nuts.isglyph
@@ -167,7 +168,7 @@ local modes = {
marginkern = 0x100000,
mathlistkern = 0x200000,
dir = 0x400000,
- localpar = 0x800000,
+ par = 0x800000,
}
local usedfont, exheight, emwidth
@@ -236,7 +237,7 @@ local function initialize()
l_space = layers.space
l_depth = layers.depth
l_dir = layers.dir
- l_localpar = layers.localpar
+ l_par = layers.par
--
if not userrule then
userrule = nuts.rules.userrule
@@ -559,6 +560,8 @@ local kernexpansion do
local f_cache = caches["kernexpansion"]
+ -- in mkiv we actually need to reconstruct but let's not do that now
+
kernexpansion = function(head,current)
local extra = getexpansion(current)
if extra ~= 0 then
@@ -624,7 +627,7 @@ local whatsit do
end
-local dir, localpar do
+local dir, par do
local dircodes = nodes.dircodes
local dirvalues = nodes.dirvalues
@@ -642,11 +645,11 @@ local dir, localpar do
par = "PAR",
}
- localpar = function(head,current)
+ par = function(head,current)
local what = "par" -- getsubtype(current)
local info = d_cache[what]
if info then
- -- print("hit localpar")
+ -- print("hit par")
else
info = sometext(formatters["L:%s"](what),usedfont,nil,c_white)
setattr(info,a_layer,l_dir)
@@ -927,7 +930,6 @@ end
local ruledglue do
local gluecodes = nodes.gluecodes
- local leadercodes = nodes.gluecodes
local userskip_code = gluecodes.userskip
local spaceskip_code = gluecodes.spaceskip
@@ -936,14 +938,11 @@ local ruledglue do
-- local keepskip_code = gluecodes.keepskip or gluecodes.userskip
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
- local parfillskip_code = gluecodes.parfillskip
local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code
local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code
local indentskip_code = gluecodes.indentskip
local correctionskip_code = gluecodes.correctionskip
- local cleaders_code = leadercodes.cleaders
-
local g_cache_v = caches["vglue"]
local g_cache_h = caches["hglue"]
@@ -967,10 +966,10 @@ local ruledglue do
[gluecodes.intermathskip] = "IM",
[gluecodes.keepskip or 99] = "KS",
[gluecodes.mathskip] = "MT",
- [leadercodes.leaders] = "NL",
- [leadercodes.cleaders] = "CL",
- [leadercodes.xleaders] = "XL",
- [leadercodes.gleaders] = "GL",
+ [gluecodes.leaders] = "NL",
+ [gluecodes.cleaders] = "CL",
+ [gluecodes.xleaders] = "XL",
+ [gluecodes.gleaders] = "GL",
-- true = "VS",
-- false = "HS",
[leftskip_code] = "LS",
@@ -978,7 +977,6 @@ local ruledglue do
[spaceskip_code] = "SP",
[xspaceskip_code] = "XS",
[zerospaceskip_code] = "ZS",
- [parfillskip_code] = "PR",
[parfillleftskip_code] = "PL",
[parfillrightskip_code] = "PR",
[indentskip_code] = "IN",
@@ -999,7 +997,7 @@ 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 == parfillskip_code or subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then
+ 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
if width > 0 then
@@ -1252,7 +1250,7 @@ do
local marginkern_code = nodecodes.marginkern
local mathlistkern_code = nodecodes.mathlistkern
local dir_code = nodecodes.dir
- local localpar_code = nodecodes.localpar
+ local par_code = nodecodes.par
local kerncodes = nodes.kerncodes
local fontkern_code = kerncodes.fontkern
@@ -1289,7 +1287,7 @@ do
local trace_space = false
local trace_depth = false
local trace_dir = false
- local trace_localpar = false
+ local trace_par = false
local current = head
local previous = nil
local attr = unsetvalue
@@ -1334,7 +1332,7 @@ do
trace_marginkern = false
trace_mathlistkern = false
trace_dir = false
- trace_localpar = false
+ trace_par = false
if id == kern_code then
goto kern
else
@@ -1431,9 +1429,9 @@ do
if trace_dir then
head, current = dir(head,current)
end
- elseif id == localpar_code then
- if trace_localpar then
- head, current = localpar(head,current)
+ elseif id == par_code then
+ if trace_par then
+ head, current = par(head,current)
end
end
goto next
diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv
index b261747c1..5357c8414 100644
--- a/tex/context/base/mkiv/trac-vis.mkiv
+++ b/tex/context/base/mkiv/trac-vis.mkiv
@@ -70,26 +70,18 @@
\unexpanded\def\ruledmbox#1{\ruledhbox{\startimath#1\stopimath}}
-\ifcase\contextlmtxmode
+\unexpanded\def\sys_ruled_vcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}}
- \unexpanded\def\sys_ruled_vcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}}
+\unexpanded\def\ruledvcenter
+ {\ruledvbox\bgroup
+ \dowithnextboxcs\syst_boxes_ruled_vcenter_finish\ruledvbox}
- \unexpanded\def\ruledvcenter
- {\ruledvbox\bgroup
- \dowithnextboxcs\syst_boxes_ruled_vcenter_finish\ruledvbox}
+\def\syst_boxes_ruled_vcenter_finish
+ {\ruledhpack{\normalstartimath\ruledvcenter{\box\nextbox}\normalstopimath}%
+ \egroup}
- \def\syst_boxes_ruled_vcenter_finish
- {\ruledhpack{\normalstartimath\ruledvcenter{\box\nextbox}\normalstopimath}%
- \egroup}
-
- \prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everymath
- \prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everydisplay
-
-\else
-
- \unexpanded\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}}
-
-\fi
+\prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everymath
+\prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everydisplay
\appendtoks
\ifcase\c_syst_visualizers_state\else
diff --git a/tex/context/base/mkiv/trac-vis.mkxl b/tex/context/base/mkiv/trac-vis.mkxl
new file mode 100644
index 000000000..77df80848
--- /dev/null
+++ b/tex/context/base/mkiv/trac-vis.mkxl
@@ -0,0 +1,219 @@
+%D \module
+%D [ file=trac-vis, % replaces supp-vis plus some s-* modules
+%D version=2012.06.23, % 1996.10.21,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=Visualization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The old visual debugger dates from 1996 and started out as joke. In practice
+%D it's not used that often although the \type {\ruledhbox} cum suis macros come
+%D in handy when writing code. In the process of luafication some additional
+%D tracing options were tested, for instance showing font kerns. As part of the
+%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider
+%D all these features. The old code is gone and the new code will get extended
+%D when needed. We still provide placeholders for some old visualization commands
+%D but they might go away.
+%D
+%D Control over what gets visualized happens with the tracker command:
+%D
+%D \enabletrackers[visualizers.*]
+%D
+%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type
+%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type
+%D {makeup}, \type {whatsit}, \type{glyph}.
+%D
+%D In due time some special visualzation of math will move here as well.
+
+\writestatus{loading}{ConTeXt Tracing Macros / Visualization}
+
+\registerctxluafile{trac-vis}{autosuffix,optimize}
+
+\unprotect
+
+\newconstant\c_syst_visualizers_state
+\newtoks \t_syst_visualizers_optimize
+
+% \definesystemattribute[visual][public,global] % already defined
+
+% no, but can become an option:
+%
+% \appendtoks
+% \c_attr_visual\attributeunsetvalue
+% \to \everybeforepagebody
+
+%D We only provide box visualizers as they can come in handy for testing
+%D macros. In due time we will move some of the m-visual code here too.
+
+\aliased\let\syst_visualizers_hbox \hbox
+\aliased\let\syst_visualizers_vbox \vbox
+\aliased\let\syst_visualizers_vtop \vtop
+\aliased\let\syst_visualizers_vcenter\vcenter
+\aliased\let\syst_visualizers_hpack \hpack
+\aliased\let\syst_visualizers_vpack \vpack
+\aliased\let\syst_visualizers_tpack \tpack
+
+\permanent\protected\def\ruledhbox {\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} }
+\permanent\protected\def\ruledhpack {\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} }
+\permanent\protected\def\ruledvbox {\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} }
+\permanent\protected\def\ruledvpack {\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} }
+\permanent\protected\def\ruledvtop {\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} }
+\permanent\protected\def\ruledtpack {\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} }
+\permanent\protected\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual{simplevbox} }
+\permanent\protected\def\ruledmbox #1{\ruledhbox{\startimath#1\stopimath}}
+
+\appendtoks
+ \ifcase\c_syst_visualizers_state\else
+ \syst_visualizers_speedup
+ \fi
+\to \everyshipout
+
+\appendtoks
+ \glet\syst_visualizers_speedup\relax
+ \global\t_syst_visualizers_optimize\emptytoks
+\to \t_syst_visualizers_optimize
+
+\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize}
+
+\appendtoks
+% \enforced\global\protected\edef\ruledhbox {\syst_visualizers_hbox attr \visualattribute \number\clf_getvisual{simplehbox} }
+% \enforced\global\protected\edef\ruledhpack {\syst_visualizers_hpack attr \visualattribute \number\clf_getvisual{simplehbox} }
+% \enforced\global\protected\edef\ruledvbox {\syst_visualizers_vbox attr \visualattribute \number\clf_getvisual{simplevbox} }
+% \enforced\global\protected\edef\ruledvpack {\syst_visualizers_vpack attr \visualattribute \number\clf_getvisual{simplevbox} }
+% \enforced\global\protected\edef\ruledvtop {\syst_visualizers_vtop attr \visualattribute \number\clf_getvisual{simplevtop} }
+% \enforced\global\protected\edef\ruledtpack {\syst_visualizers_tpack attr \visualattribute \number\clf_getvisual{simplevtop} }
+% \enforced\global\protected\edef\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \number\clf_getvisual{simplevbox} }
+\to \t_syst_visualizers_optimize
+
+\permanent\tolerant\protected\def\showmakeup[#1]%
+ {\ifarguments
+ \clf_setvisual{makeup}%
+ \else
+ \clf_setvisual{#1}%
+ \fi}
+
+\permanent\protected\def\showallmakeup {\clf_setvisual{all}\showstruts}
+\permanent\protected\def\showboxes {\clf_setvisual{boxes}}
+\permanent\protected\def\showglyphs {\clf_setvisual{glyph}}
+\permanent\protected\def\showfontkerns {\clf_setvisual{fontkern}}
+\permanent\protected\def\showfontitalics {\clf_setvisual{italic}}
+\permanent\protected\def\showglyphdata {\showglyphs\showfontkerns\showfontitalics}
+\permanent\protected\def\showfontexpansion{\clf_setvisual{expansion}}
+
+\permanent\tolerant\protected\def\setvisualizerfont[#1]% somename at 4pt
+ {\begingroup
+ \iftok{#1}\emptytoks
+ \definedfont[Mono at 4pt]%
+ \else
+ \definedfont[#1]%
+ \fi
+ \clf_setvisualfont\fontid\font
+ \endgroup}
+
+\permanent\protected\def\resetvisualizers
+ {\c_attr_visual\attributeunsetvalue}
+
+%D New (these might also be a visualizers):
+
+% \definecolor[f:r:t][a=1,t=.25,r=1]
+% \definecolor[f:g:t][a=1,t=.25,g=1]
+% \definecolor[f:b:t][a=1,t=.25,b=1]
+% \definecolor[f:c:t][a=1,t=.25,c=1]
+% \definecolor[f:m:t][a=1,t=.25,m=1]
+% \definecolor[f:y:t][a=1,t=.25,y=1]
+% \definecolor[f:k:t][a=1,t=.25,s=0]
+
+\permanent\protected\def\filledhboxr{\node_backgrounds_boxes_add\hbox[f:r:t]}
+\permanent\protected\def\filledhboxg{\node_backgrounds_boxes_add\hbox[f:g:t]}
+\permanent\protected\def\filledhboxb{\node_backgrounds_boxes_add\hbox[f:b:t]}
+\permanent\protected\def\filledhboxc{\node_backgrounds_boxes_add\hbox[f:c:t]}
+\permanent\protected\def\filledhboxm{\node_backgrounds_boxes_add\hbox[f:m:t]}
+\permanent\protected\def\filledhboxy{\node_backgrounds_boxes_add\hbox[f:y:t]}
+\permanent\protected\def\filledhboxk{\node_backgrounds_boxes_add\hbox[f:k:t]}
+
+%D Overload:
+
+\protected\def\spac_struts_vide_hbox
+ {\hbox attr \visualattribute \clf_getvisual{strut} }
+
+\appendtoks
+ \normalexpanded{\protected\xdef\spac_struts_vide_hbox\expandafter{\spac_struts_vide_hbox}}%
+\to \t_syst_visualizers_optimize
+
+%D For manuals:
+
+\permanent\protected\def\markfonts#1%
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\getbuffer}%
+ \clf_markvisualfonts\scratchbox
+ \unhbox\scratchbox
+ \endgroup}
+
+% As demo:
+%
+% \startbuffer
+% \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}}
+% \blank
+% \moveleft1cm\hbox{left}
+% \blank
+% \hbox{normal}
+% \blank
+% \moveright1cm\hbox{right}
+% \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+%
+% \startbuffer
+% \moveleft1cm\vbox{left}
+% \blank
+% \vbox{normal}
+% \blank
+% \moveright1cm\vbox{right}
+% \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+
+%D We keep this one:
+
+\permanent\protected\def\dontinterfere
+ {\reseteverypar
+ \parindent\zeropoint
+ \parskip \zeropoint
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+%D We keep these for a while:
+
+\let\ruledhss \hss
+\let\ruledhfil \hfil
+\let\ruledhfill \hfill
+\let\ruledhfilll \hfilll
+\let\ruledhfilneg \hfilneg
+\let\ruledhfillneg \hfillneg
+\let\ruledhfilllneg \hfilllneg
+\let\ruledvss \vss
+\let\ruledvfil \vfil
+\let\ruledvfill \vfill
+\let\ruledvfilll \vfilll
+\let\ruledvfilneg \vfilneg
+\let\ruledvfillneg \vfillneg
+\let\ruledvfilllneg \vfilllneg
+\let\ruledhskip \hskip
+\let\ruledvskip \vskip
+\let\ruledkern \kern
+\let\ruledhglue \hglue
+\let\ruledvglue \vglue
+\let\ruledmkern \mkern
+\let\ruledmskip \mskip
+\let\ruledpenalty \penalty
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/type-ini.mklx b/tex/context/base/mkiv/type-ini.mklx
index 1cb9bc2e5..f6dd7780d 100644
--- a/tex/context/base/mkiv/type-ini.mklx
+++ b/tex/context/base/mkiv/type-ini.mklx
@@ -27,8 +27,6 @@
\unprotect
-\definesystemvariable {ts} % TypeScript / for the moment we keep this one
-
\newcount \c_font_typescripts_n_of_preloaded
\newconditional\c_font_typescripts_quit
\newtoks \c_font_typescripts_document
@@ -69,7 +67,7 @@
\installmacrostack\m_font_typescripts_two
\installmacrostack\m_font_typescripts_three
-\let\t_font_typescripts\relax % uses as synonym
+\mutable\let\t_font_typescripts\relax % uses as synonym
\installcorenamespace{typescriptcache}
\installcorenamespace{typescriptfiles}
@@ -97,29 +95,41 @@
%D that one is also grouped and loading bodyfonts grouped is a real bad idea.
%D Ignoring all spaces is also not a solution. So, our verdict is: no catch.
-\unexpanded\def\starttypescriptcollection
+\permanent\protected\def\starttypescriptcollection % redefined on the fly
{\dosingleempty\font_typescripts_collection_start}
\def\font_typescripts_collection_start[#tag]%
{}
-\let\stoptypescriptcollection\relax
+\permanent\let\stoptypescriptcollection\relax
+
+\permanent\protected\def\usetypescriptfile[#filename]%
+ {\iftok{#filename}{\v!reset}%
+ \let\typescriptfiles\empty
+ \else
+ \splitfilename{#filename}%
+ \addtocommalist\splitoffbase\typescriptfiles
+ \fi}
+
+\installmacrostack\stoptypescript
-\unexpanded\def\usetypescriptfile[#filename]%
- {\doifelse{#filename}\v!reset
- {\let\typescriptfiles\empty}
- {\splitfilename{#filename}%
- \addtocommalist\splitoffbase\typescriptfiles}}
+% \permanent\protected\def\usetypescript {\dotripleempty\font_typescripts_use_one}
+% \permanent\protected\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two}
+%
+% \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use}
+% \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use}
+%
+% \protected\def\font_typescripts_use[#one][#two][#three]%
-\unexpanded\def\usetypescript {\dotripleempty\font_typescripts_use_one}
-\unexpanded\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two}
+% todo: just pass the method ... also further on then .. first test
\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use}
\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use}
-\installmacrostack\stoptypescript
+\permanent\protected\def\usetypescript {\font_typescripts_use_one}
+\permanent\protected\def\usetypescriptexact{\font_typescripts_use_two}
-\unexpanded\def\font_typescripts_use[#one][#two][#three]%
+\tolerant\protected\def\font_typescripts_use[#one]#spacer[#two]#spacer[#three]%
{\push_macro_m_font_typescripts_one
\push_macro_m_font_typescripts_two
\push_macro_m_font_typescripts_three
@@ -159,20 +169,20 @@
\let\font_typescripts_use_inline\font_typescripts_use_display
-\unexpanded\def\preloadtypescripts
+\permanent\protected\def\preloadtypescripts
{\ifproductionrun\settrue\c_font_typescripts_preload\fi}
\prependtoks
\preloadtypescripts
\to \everyjob
-\unexpanded\def\loadtypescriptfile[#1]%
+\permanent\protected\def\loadtypescriptfile[#1]%
{\push_macro_typescriptstate
\let\typescriptstate\plustwo % assumes 2 at the outer level
\clf_loadtypescriptfile{#1}%
\pop_macro_typescriptstate}
-\unexpanded\def\loadfoundtypescriptfile#1#2% name foundname / not a user command
+\permanent\protected\def\loadfoundtypescriptfile#1#2% name foundname / not a user command
{\startreadingfile
\unprotect
\pushendofline
@@ -181,17 +191,17 @@
\protect
\stopreadingfile}
-\unexpanded\def\quittypescriptscanning
+\permanent\protected\def\quittypescriptscanning
{\settrue\c_font_typescripts_quit} % public
-\def\font_typescripts_start_store#definitions\stoptypescript
+\permanent\protected\def\font_typescripts_start_store#definitions\stoptypescript
{\global\advance\c_font_typescripts_n_of_preloaded\plusone
\expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
{\starttypescript#definitions\stoptypescript}%
\gtoksapp\t_font_typescripts\expandafter
{\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
-\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection
+\permanent\protected\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection
{\global\advance\c_font_typescripts_n_of_preloaded\plusone
\expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
{\starttypescriptcollection#definitions\stoptypescriptcollection}%
@@ -215,6 +225,7 @@
\def\font_typescript_process_typescript_file_and_store
{\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname
+% {\aliased\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname
\ifx\t_font_typescripts\relax
\font_typescript_process_typescript_store_indeed
\fi
@@ -223,8 +234,8 @@
\def\font_typescript_process_typescript_store_indeed
{\newtoks\t_font_typescripts % is \relaxed elsewhere
\begingroup
- \let\starttypescript \font_typescripts_start_store
- \let\starttypescriptcollection\font_typescripts_collection_start_store
+ \enforced\let\starttypescript \font_typescripts_start_store
+ \enforced\let\starttypescriptcollection\font_typescripts_collection_start_store
\font_typescript_process_typescript_file
\endgroup
\expandafter\let\csname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts}
@@ -232,10 +243,7 @@
\def\font_typescript_process_typescript_file
{\clf_doprocesstypescriptfile{\currenttypefile}}
-\unexpanded\def\usetypescriptonce
- {\dotripleempty\font_typescripts_use_once}
-
-\def\font_typescripts_use_once[#one][#two][#three]%
+\permanent\tolerant\protected\def\usetypescriptonce[#one]#spacer[#two]#spacer[#three]%
{\ifcsname\??typescriptonce#one:#two:#three\endcsname
\writestatus\m!fonts{once (#one) (#two) (#three)}%
\else
@@ -245,13 +253,10 @@
% \definetypescriptsynonym[lbr][cmr]
-\unexpanded\def\definetypescriptsynonym
- {\dodoubleempty\font_typescripts_synonym_define}
-
-\def\font_typescripts_synonym_define[#name][#synonym]%
+\permanent\tolerant\protected\def\definetypescriptsynonym[#name]#spacer[#synonym]%
{\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi}
-\def\truetypescript#name% recursive so no \lastnamedcs
+\permanent\def\truetypescript#name% recursive so no \lastnamedcs
{\ifcsname\??typescriptsynonyms#name\endcsname
%\expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname
\expandafter\truetypescript\lastnamedcs
@@ -269,7 +274,7 @@
\settrue\c_font_typescripts_first_pass
\to \everyjob
-\unexpanded\def\starttypescript
+\permanent\protected\def\starttypescript
{\ifcase\typescriptstate
% 0 = skip
\expandafter\font_typescripts_start_gobble
@@ -338,7 +343,7 @@
\def\font_typescripts_start_process_indeed
{\push_macro_fontclass}
-\unexpanded\def\stoptypescript
+\permanent\protected\def\stoptypescript
{\pop_macro_fontclass}
\def\font_typescripts_check#asked#target#followup[#value]% script use value next
@@ -366,23 +371,15 @@
\expandafter\font_typescripts_start_gobble
\fi}
-\def\extendtypescriptmatch
+\permanent\protected\def\extendtypescriptmatch
{\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}}
%D Map files will go away in \LUATEX, but till that happens we use stripped down
%D support for loading them.
-\unexpanded\def\loadmapfile{\dosingleempty\font_map_load_file}
-\unexpanded\def\loadmapline{\dodoubleempty\font_map_load_line}
-
-\def\font_map_load_file[#filename]%
- {\clf_loadmapfile{#filename}}
-
-\def\font_map_load_line[#kind][#data]%
- {\clf_loadmapline{#kind}{#data}}
-
-\unexpanded\def\forgetmapfiles
- {\clf_resetmapfiles}
+\permanent\tolerant\protected\def\loadmapfile [#filename]{\clf_loadmapfile{#filename}}
+\permanent\tolerant\protected\def\loadmapline [#kind]#spacer[#data]{\clf_loadmapline{#kind}{#data}}
+\permanent \protected\def\forgetmapfiles {\clf_resetmapfiles}
% \prependtoks
% \loadmapfile[mkiv-base.map]% can't we preload this one?
@@ -398,10 +395,13 @@
% \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree]
% \stoptypescript
-\unexpanded\def\definetypescriptprefix
- {\dodoubleargument\font_typescripts_define_prefix}
+% \protected\def\definetypescriptprefix
+% {\dodoubleargument\font_typescripts_define_prefix}
+%
+% \def\font_typescripts_define_prefix[#name][#prefix]%
+% {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global
-\def\font_typescripts_define_prefix[#name][#prefix]%
+\permanent\tolerant\protected\def\definetypescriptprefix[#name]#spacer[#prefix]%
{\setgvalue{\??typescriptprefix#name}{#prefix}} % made global
\def\typescriptprefix#name%
@@ -417,9 +417,6 @@
% \definetypeface [joke] [rm] [serif] [lucida] [size] [settings]
% \definetypeface [joke] [specification]
-\unexpanded\def\definetypeface
- {\dosixtupleargument\font_typefaces_define}
-
\appendtoks
\font_helpers_reset_fontclass_math_families\fontclass
\to \everybeforedefinetypeface
@@ -428,7 +425,7 @@
\settrue\autotypescripts
-\unexpanded\def\trycurrentfontclass#typeface%
+\protected\def\trycurrentfontclass#typeface%
{\ifconditional\autotypescripts
\usetypescript[#typeface]%
\ifcsname\??fontclassyes#typeface\endcsname
@@ -451,16 +448,25 @@
%D Now we define:
-\def\font_typefaces_define
- {\iffifthargument
- \expandafter\font_typefaces_define_a
- \orelse\iffourthargument
- \expandafter\font_typefaces_define_b
- \orelse\ifthirdargument
- \expandafter\font_typefaces_define_c
- \else
+\permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]%
+ {\ifarguments
+ \expandafter\font_typefaces_define_e
+ \or
\expandafter\font_typefaces_define_d
- \fi}
+ \or
+ \expandafter\font_typefaces_define_d
+ \or
+ \expandafter\font_typefaces_define_c
+ \or
+ \expandafter\font_typefaces_define_b
+ \or
+ \expandafter\font_typefaces_define_a
+ \or
+ \expandafter\font_typefaces_define_a
+ \fi[#name][#style][#fontshape][#fontname][#fontsize][#settings]}
+
+\def\font_typefaces_define_e[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+ {}
\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
{\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi
@@ -477,13 +483,13 @@
\font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
\font_typefaces_defining_stop}
-\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#dummya][#dummyb]%
- {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#dummyb]}
+\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#discard][#discard]%
+ {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#discard]}
-\def\font_typefaces_define_c[#name][#style][#dummya][#dummyb][#dummyc][#dummyd]%
+\def\font_typefaces_define_c[#name][#style][#discard][#discard][#discard][#discard]%
{\font_typefaces_define_indeed[#name][#style]}
-\def\font_typefaces_define_d[#name][#specification][#dummya][#dummyb][#dummyc][#dummyd]% use definitions in lfg file
+\def\font_typefaces_define_d[#name][#specification][#discard][#discard][#discard][#discard]% use definitions in lfg file
{\clf_definetypeface{#name}{#specification}}
\def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition
@@ -496,21 +502,62 @@
\setugvalue{#name}{\switchtotypeface[#name][#style]}%
\fi}}
+% needs testing first ... let'd do it stepwise
+
+% \permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]%
+% {\ifarguments
+% \or
+% \clf_definetypeface{#name}{#specification}%
+% \or
+% \clf_definetypeface{#name}{#specification}%
+% \or
+% \font_typefaces_define_simplex[#name][#style]%
+% \or
+% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][\s!default][#discard]%
+% \else
+% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+% \fi}
+%
+% \def\font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+% {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi
+% \font_typefaces_define_simplex[#name][#style]%
+% \font_typefaces_defining_start{#name}{#style}{#settings}%
+% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+% \iftypescriptfound
+% % we're okay
+% \orelse\ifconditional\autotypescripts
+% \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi
+% \usetypescriptfile[#fontname]%
+% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]%
+% \fi
+% \font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
+% \font_typefaces_defining_stop}
+%
+% \def\font_typefaces_define_simplex[#name][#style]% saveguard against redefinition
+% {\doifsomething{#name}
+% {\ifcsname\??typescriptdefaultstyles#name\endcsname \else
+% \registerfontclass{#name}%
+% \setxvalue{\??typescriptdefaultstyles#name}{#style}%
+% \fi
+% \ifcsname#name\endcsname \else
+% \setugvalue{#name}{\switchtotypeface[#name][#style]}%
+% \fi}}
+
\def\font_typefaces_defining_start#name#style#settings%
- {\let\@@tsrscale \!!plusone % as we push/pop
- \let\@@tsfeatures \empty
- \let\@@tsfallbacks \empty
- \let\@@tsgoodies \empty
- \let\@@tsdirection \empty
- \let\@@tsdesignsize\empty
- \geteparameters[\??ts][#settings]% todo raw
+ {\let\m_ts_rscale \!!plusone % as we push/pop
+ \let\m_ts_features \empty
+ \let\m_ts_fallbacks \empty
+ \let\m_ts_goodies \empty
+ \let\m_ts_direction \empty
+ \let\m_ts_designsize\empty
+ \geteparameters[m_ts_][#settings]% todo raw ... no need for key interpretation
\push_macro_fontclass
\push_macro_fontclassstyle
\setcurrentfontclass{#name}%
- \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection
+ \savefontclassparameters{#style}\m_ts_rscale\m_ts_features\m_ts_fallbacks\m_ts_goodies\m_ts_designsize\m_ts_direction
\the\everybeforedefinetypeface}
-\def\tsvar#key#default% undocumented and unofficial
+\permanent\def\tsvar#key#default% undocumented and unofficial
{\expandafter\ifempty\csname\??ts#key\endcsname
#default%
\else
@@ -528,39 +575,77 @@
\font_typescripts_use_one[#fontshape][#fontsize][\s!size]%
\font_typefaces_defining_stop}
-\unexpanded\def\setuptypeface% [class] [settings]
- {\dodoubleempty\font_typefaces_setup}
-
-\unexpanded\def\switchtotypeface% [class] [settings]
- {\dodoubleempty\font_typefaces_switch}
+% \protected\def\setuptypeface% [class] [settings]
+% {\dodoubleempty\font_typefaces_setup}
+%
+% \protected\def\switchtotypeface% [class] [settings]
+% {\dodoubleempty\font_typefaces_switch}
+%
+% \def\font_typefaces_setup[#class][#settings]%
+% {\setcurrentfontclass{#class}%
+% \let\globalfontclass\fontclass
+% \ifsecondargument
+% \setupbodyfont[#settings]%
+% \orelse\ifempty\fontclass
+% \setupbodyfont[\s!rm]%
+% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+% %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+% \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
+% \else
+% \setupbodyfont[\s!rm]%
+% \fi
+% \ifmmode\mr\else\tf\fi} % needed ?
+%
+% \def\font_typefaces_switch[#class]#spacer[#settings]%
+% {\setcurrentfontclass{#class}%
+% \let\globalfontclass\globalfontclass
+% \ifsecondargument
+% \switchtobodyfont[#settings]%
+% \orelse\ifempty\fontclass
+% \switchtobodyfont[\s!rm]%
+% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+% %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+% \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
+% \else
+% \switchtobodyfont[\s!rm]%
+% \fi
+% \ifmmode\mr\else\tf\fi} % needed ?
-\def\font_typefaces_setup[#class][#settings]%
- {\setcurrentfontclass{#class}%
- \let\globalfontclass\fontclass
- \ifsecondargument
+\permanent\tolerant\protected\def\setuptypeface[#class]#spacer[#settings]%
+ {\ifarguments
+ \or
+ \setcurrentfontclass{#class}%
+ \let\globalfontclass\fontclass
+ \ifempty\fontclass
+ \setupbodyfont[\s!rm]%
+ \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
+ \else
+ \setupbodyfont[\s!rm]%
+ \fi
+ \or
+ \setcurrentfontclass{#class}%
+ \let\globalfontclass\fontclass
\setupbodyfont[#settings]%
- \orelse\ifempty\fontclass
- \setupbodyfont[\s!rm]%
- \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
- %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
- \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
- \else
- \setupbodyfont[\s!rm]%
\fi
\ifmmode\mr\else\tf\fi} % needed ?
-\def\font_typefaces_switch[#class][#settings]%
- {\setcurrentfontclass{#class}%
- \let\globalfontclass\globalfontclass
- \ifsecondargument
- \switchtobodyfont[#settings]%
- \orelse\ifempty\fontclass
- \switchtobodyfont[\s!rm]%
- \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
- %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
- \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
- \else
- \switchtobodyfont[\s!rm]%
+\permanent\tolerant\protected\def\switchtotypeface[#class]#spacer[#settings]%
+ {\ifarguments
+ \or
+ \setcurrentfontclass{#class}%
+ \let\globalfontclass\globalfontclass
+ \ifempty\fontclass
+ \switchtobodyfont[\s!rm]%
+ \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
+ \else
+ \switchtobodyfont[\s!rm]%
+ \fi
+ \or
+ \setcurrentfontclass{#class}%
+ \let\globalfontclass\globalfontclass
+ \switchtobodyfont[#settings]%
\fi
\ifmmode\mr\else\tf\fi} % needed ?
@@ -573,16 +658,14 @@
%D \inherittypeface[palatino] % == [rm,ss,tt,mm]
%D \stoptyping
-\unexpanded\def\inherittypeface
- {\dotripleempty\font_typescripts_inherit_indeed}
-
-\def\font_typescripts_inherit_indeed[#name][#styles][#parentclass]%
- {\doifelsenothing{#styles}
- {\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]}
- {\doifnot{#name}{#parentclass}
- {\glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
- \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}%
- \processcommalist[#styles]\font_typescripts_inherit_check_step}}}
+\permanent\tolerant\protected\def\inherittypeface[#name]#spacer[#styles]#spacer[#parentclass]%
+ {\iftok{#styles}\emptytoks
+ \font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]%
+ \orelse\iftok{#name}{#parentclass}\else
+ \glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
+ \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}%
+ \processcommalist[#styles]\font_typescripts_inherit_check_step
+ \fi}
\let\font_typescripts_inherit_check_step\relax
@@ -612,7 +695,7 @@
\expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else
\s!Serif \fi\fi\fi}
-\unexpanded\def\font_helpers_set_fontstyle_of_fontclass
+\protected\def\font_helpers_set_fontstyle_of_fontclass
{\ifempty\fontclass
\let\fontstyle\s!rm
\orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
diff --git a/tex/context/base/mkiv/typo-bld.lua b/tex/context/base/mkiv/typo-bld.lua
index 6874d385a..269386e6c 100644
--- a/tex/context/base/mkiv/typo-bld.lua
+++ b/tex/context/base/mkiv/typo-bld.lua
@@ -242,31 +242,65 @@ end
-- this will be split into contribute_filter for these 4 so at some point
-- the check can go away
-function builders.buildpage_filter(groupcode)
- -- the next check saves 1% runtime on 1000 tufte pages
- local head = texlists.contrib_head
- local done = false
- if head then
- -- called quite often ... maybe time to remove timing
- starttiming(builders)
- if trace_page_builder then
- report(groupcode,head)
+if CONTEXTLMTXMODE > 0 then
+
+ -- Todo: contrib_head can be any head (kind of) not per se the page one so maybe I will
+ -- intercept that in the engine with page_contribute_head or so.
+
+ function builders.buildpage_filter(groupcode)
+ local head = texlists.contribute_head
+ if head then
+ local done = false
+ -- called quite often ... maybe time to remove timing
+ starttiming(builders)
+ if trace_page_builder then
+ report(groupcode,head)
+ end
+ head, done = pageactions(head,groupcode)
+ stoptiming(builders)
+ -- -- doesn't work here (not passed on?)
+ -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom")
+ texlists.contribute_head = head or nil -- needs checking
+ -- tex.setlist("contribute_head",head,head and nodes.tail(head))
+ return done and head or true -- no return value needed
+ else
+ -- happens quite often
+ if trace_page_builder then
+ report(groupcode)
+ end
+ -- return nil, false -- no return value needed
+ return nil
end
- head, done = pageactions(head,groupcode)
- stoptiming(builders)
- -- -- doesn't work here (not passed on?)
- -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom")
- texlists.contrib_head = head or nil -- needs checking
- -- tex.setlist("contrib_head",head,head and nodes.tail(head))
- return done and head or true -- no return value needed
- else
- -- happens quite often
- if trace_page_builder then
- report(groupcode)
+ end
+
+else
+
+ function builders.buildpage_filter(groupcode)
+ local head = texlists.contrib_head
+ if head then
+ local done = false
+ -- called quite often ... maybe time to remove timing
+ starttiming(builders)
+ if trace_page_builder then
+ report(groupcode,head)
+ end
+ head, done = pageactions(head,groupcode)
+ stoptiming(builders)
+ -- -- doesn't work here (not passed on?)
+ -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom")
+ texlists.contrib_head = head or nil -- needs checking
+ -- tex.setlist("contrib_head",head,head and nodes.tail(head))
+ return done and head or true -- no return value needed
+ else
+ -- happens quite often
+ if trace_page_builder then
+ report(groupcode)
+ end
+ -- return nil, false -- no return value needed
+ return nil
end
--- return nil, false -- no return value needed
- return nil
end
+
end
registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc")
diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua
index d670c5319..89eb7e52d 100644
--- a/tex/context/base/mkiv/typo-brk.lua
+++ b/tex/context/base/mkiv/typo-brk.lua
@@ -33,7 +33,7 @@ local getid = nuts.getid
----- getattr = nuts.getattr
local getattrlist = nuts.getattrlist
local takeattr = nuts.takeattr
-local getlang = nuts.getlang
+local getlanguage = nuts.getlanguage
local isglyph = nuts.isglyph
local setattr = nuts.setattr
@@ -168,7 +168,7 @@ methods[2] = function(head,start) -- ( => (-
head, start, replace = remove_node(head,start)
local post = copy_node(replace)
local hyphen = copy_node(post)
- setchar(hyphen,languages.prehyphenchar(getlang(post)))
+ setchar(hyphen,languages.prehyphenchar(getlanguage(post)))
setlink(post,hyphen)
head, start = insert_node_before(head,start,new_disc(nil,post,replace))
setattrlist(start,replace)
@@ -184,7 +184,7 @@ methods[3] = function(head,start) -- ) => -)
head, start, replace = remove_node(head,start)
local pre = copy_node(replace)
local hyphen = copy_node(pre)
- setchar(hyphen,languages.prehyphenchar(getlang(pre)))
+ setchar(hyphen,languages.prehyphenchar(getlanguage(pre)))
setlink(hyphen,pre)
head, start = insert_node_before(head,start,new_disc(hyphen,nil,replace)) -- so not pre !
setattrlist(start,tmp)
@@ -264,7 +264,7 @@ function breakpoints.handler(head)
-- setattr(current,a_breakpoints,unsetvalue) -- should not be needed
-- for now we collect but when found ok we can move the handler here
-- although it saves nothing in terms of performance
- local lang = getlang(current)
+ local lang = getlanguage(current)
local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[languages.numbers[lang]] or cmap[""])
if smap then
local skip = smap.skip
@@ -322,7 +322,7 @@ function breakpoints.handler(head)
local cmap = data[3]
local smap = data[4]
-- we do a sanity check for language
- -- local lang = getlang(start)
+ -- local lang = getlanguage(start)
-- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
-- if smap then
local nleft = smap.nleft
diff --git a/tex/context/base/mkiv/typo-chr.lua b/tex/context/base/mkiv/typo-chr.lua
index 7a0f1fd75..bb3883b33 100644
--- a/tex/context/base/mkiv/typo-chr.lua
+++ b/tex/context/base/mkiv/typo-chr.lua
@@ -91,7 +91,7 @@ local boundarycodes = nodes.boundarycodes
local subtypes = nodes.subtypes
local glyph_code = nodecodes.glyph
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local boundary_code = nodecodes.boundary
local wordboundary_code = boundarycodes.word
@@ -175,7 +175,7 @@ local function pickup(head,tail,str)
while true do
local prev = first.prev
if prev and prev[a_marked] == attr then
- if prev.id == localpar_code then -- and start_of_par(prev)
+ if prev.id == par_code then -- and start_of_par(prev)
break
else
first = prev
diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua
index 7be74caa1..ac72ae394 100644
--- a/tex/context/base/mkiv/typo-dha.lua
+++ b/tex/context/base/mkiv/typo-dha.lua
@@ -78,7 +78,7 @@ local math_code = nodecodes.math
local kern_code = nodecodes.kern
local glue_code = nodecodes.glue
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local dirvalues = nodes.dirvalues
local lefttoright_code = dirvalues.lefttoright
@@ -332,7 +332,7 @@ local function process(start)
end
textdir = autodir
setprop(current,"direction",true)
- elseif id == localpar_code and start_of_par(current) then
+ elseif id == par_code and start_of_par(current) then
local direction = getdirection(current)
if direction == righttoleft_code then
autodir = -1
diff --git a/tex/context/base/mkiv/typo-dir.mkxl b/tex/context/base/mkiv/typo-dir.mkxl
index 577434e56..e9c7e47d6 100644
--- a/tex/context/base/mkiv/typo-dir.mkxl
+++ b/tex/context/base/mkiv/typo-dir.mkxl
@@ -33,18 +33,18 @@
\installsimplecommandhandler \??directions {directions} \??directions % no \define... yet
-\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark
-\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark
+\permanent\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark % expandable
+\permanent\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark % expandable
-\unexpanded\def\setdirection[#1]% todo: symbolic names
+\permanent\protected\def\setdirection[#1]% todo: symbolic names
{\clf_setdirection#1\relax}
-% \unexpanded\def\resetdirection
+% \protected\def\resetdirection
% {\clf_setdirection\zerocount}
%
% is in fact:
-\unexpanded\def\resetdirection
+\protected\def\resetdirection
{\c_attr_directions\attributeunsetvalue}
\newconstant\directionsbidimode % this one might become pivate
@@ -100,16 +100,16 @@
\c!break=\v!both, % experimental value, maybe \v!no will be default (bad name too)
\c!fences=\v!yes]
-\unexpanded\edef\bidilre{\normalUchar"202A}
-\unexpanded\edef\bidirle{\normalUchar"202B}
-\unexpanded\edef\bidipop{\normalUchar"202C}
-\unexpanded\edef\bidilro{\normalUchar"202D}
-\unexpanded\edef\bidirlo{\normalUchar"202E}
+\permanent\protected\edef\bidilre{\normalUchar"202A}
+\permanent\protected\edef\bidirle{\normalUchar"202B}
+\permanent\protected\edef\bidipop{\normalUchar"202C}
+\permanent\protected\edef\bidilro{\normalUchar"202D}
+\permanent\protected\edef\bidirlo{\normalUchar"202E}
-\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi}
-\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi}
-\unexpanded\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi}
-\unexpanded\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi}
+\permanent\protected\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi}
+\permanent\protected\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi}
+\permanent\protected\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi}
+\permanent\protected\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi}
% for the moment: \setdirection[\plusone]
@@ -143,7 +143,7 @@
% end
% \stopluacode
%
-% \unexpanded\def\biditest#1#2#3% font text raw
+% \protected\def\biditest#1#2#3% font text raw
% {\dontleavehmode\hbox
% {\framed[offset=overlay]{\tttf#2}\quad
% \enabletrackers[typesetters.directions]%
diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua
index ad4a80a57..12864e52d 100644
--- a/tex/context/base/mkiv/typo-drp.lua
+++ b/tex/context/base/mkiv/typo-drp.lua
@@ -82,7 +82,7 @@ local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local actions = { }
initials.actions = actions
@@ -270,7 +270,7 @@ actions[v_default] = function(head,setting)
end
-- We pack so that successive handling cannot touch the dropped cap. Packaging
-- in a hlist is also needed because we cannot locally adapt e.g. parindent (not
- -- yet stored in with localpar).
+ -- yet stored in with par).
local prev = getprev(first)
local next = getnext(last)
--
@@ -339,7 +339,7 @@ end
-- we can count ... when all done, we can disable ...
function initials.handler(head)
- if getid(head) == localpar_code and start_of_par(head) then
+ if getid(head) == par_code and start_of_par(head) then
local settings = getprop(head,a_initial)
if settings then
disableaction("processors","typesetters.initials.handler")
diff --git a/tex/context/base/mkiv/typo-dua.lua b/tex/context/base/mkiv/typo-dua.lua
index 92cca7ae4..5e1d4c109 100644
--- a/tex/context/base/mkiv/typo-dua.lua
+++ b/tex/context/base/mkiv/typo-dua.lua
@@ -99,7 +99,7 @@ local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local parfillskip_code = gluecodes.parfillskip
@@ -337,7 +337,7 @@ local function get_baselevel(head,list,size,direction)
-- This is an adapted version:
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
- elseif getid(head) == localpar_code and start_of_par(head) then
+ elseif getid(head) == par_code and start_of_par(head) then
direction = getdirection(head)
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
@@ -769,8 +769,8 @@ local function apply_to_list(list,size,head,pardir)
enddir = false
end
elseif begindir then
- if id == localpar_code and start_of_par(current) then
- -- localpar should always be the 1st node
+ if id == par_code and start_of_par(current) then
+ -- par should always be the 1st node
local d = new_direction(begindir)
-- setprop(d,"directions",true)
-- setattrlist(d,current)
diff --git a/tex/context/base/mkiv/typo-dub.lua b/tex/context/base/mkiv/typo-dub.lua
index ccbcc0a06..88b3361da 100644
--- a/tex/context/base/mkiv/typo-dub.lua
+++ b/tex/context/base/mkiv/typo-dub.lua
@@ -87,7 +87,7 @@ local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local parfillskip_code = gluecodes.parfillskip
@@ -398,7 +398,7 @@ end
local function get_baselevel(head,list,size,direction)
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
- elseif getid(head) == localpar_code and start_of_par(head) then
+ elseif getid(head) == par_code and start_of_par(head) then
direction = getdirection(head)
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
@@ -902,8 +902,8 @@ local function apply_to_list(list,size,head,pardir)
enddir = false
end
elseif begindir then
- if id == localpar_code and start_of_par(current) then
- -- localpar should always be the 1st node
+ if id == par_code and start_of_par(current) then
+ -- par should always be the 1st node
local d = new_direction(begindir)
-- setprop(d,"directions",true)
-- setattrlist(d,current)
diff --git a/tex/context/base/mkiv/typo-duc.lua b/tex/context/base/mkiv/typo-duc.lua
index a1ee14a28..6e4f27de2 100644
--- a/tex/context/base/mkiv/typo-duc.lua
+++ b/tex/context/base/mkiv/typo-duc.lua
@@ -51,70 +51,73 @@ local utfchar = utf.char
local setmetatable = setmetatable
local formatters = string.formatters
-local directiondata = characters.directions
-local mirrordata = characters.mirrors
-local textclassdata = characters.textclasses
+local directiondata = characters.directions
+local mirrordata = characters.mirrors
+local textclassdata = characters.textclasses
-local nuts = nodes.nuts
+local nuts = nodes.nuts
-local getnext = nuts.getnext
-local getid = nuts.getid
-local getsubtype = nuts.getsubtype
-local getlist = nuts.getlist
-local getchar = nuts.getchar
-local getattr = nuts.getattr
-local getprop = nuts.getprop
-local getdirection = nuts.getdirection
-local isglyph = nuts.isglyph
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getchar = nuts.getchar
+local getattr = nuts.getattr
+local getprop = nuts.getprop
+local getdirection = nuts.getdirection
+local isglyph = nuts.isglyph
-local setprop = nuts.setprop
-local setchar = nuts.setchar
-local setdirection = nuts.setdirection
-local setattrlist = nuts.setattrlist
+local setprop = nuts.setprop
+local setchar = nuts.setchar
+local setdirection = nuts.setdirection
+local setattrlist = nuts.setattrlist
-local properties = nodes.properties.data
+local properties = nodes.properties.data
-local remove_node = nuts.remove
-local insert_node_after = nuts.insert_after
-local insert_node_before = nuts.insert_before
-local start_of_par = nuts.start_of_par
+local remove_node = nuts.remove
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
+local start_of_par = nuts.start_of_par
-local nodepool = nuts.pool
-local new_direction = nodepool.direction
+local nodepool = nuts.pool
+local new_direction = nodepool.direction
-local nodecodes = nodes.nodecodes
-local gluecodes = nodes.gluecodes
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
-local glyph_code = nodecodes.glyph
-local glue_code = nodecodes.glue
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local math_code = nodecodes.math
-local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local math_code = nodecodes.math
+local dir_code = nodecodes.dir
+local par_code = nodecodes.par
+local penalty_code = nodecodes.penalty
-local parfillskip_code = gluecodes.parfillskip
+local parfillskip_code = gluecodes.parfillskip
+local parfillleftskip_code = gluecodes.parfillleftskip
-local dirvalues = nodes.dirvalues
-local lefttoright_code = dirvalues.lefttoright
-local righttoleft_code = dirvalues.righttoleft
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
-local maximum_stack = 0xFF
+local maximum_stack = 0xFF
-local a_directions = attributes.private('directions')
+local a_directions = attributes.private('directions')
-local directions = typesetters.directions
-local setcolor = directions.setcolor
-local getfences = directions.getfences
+local directions = typesetters.directions
+local setcolor = directions.setcolor
+local getfences = directions.getfences
-local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end)
------ analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end)
+local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end)
+----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end)
-local report_directions = logs.reporter("typesetting","directions three")
+local report_directions = logs.reporter("typesetting","directions three")
-local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
-local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end)
-local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end)
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
+local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end)
+local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end)
-- strong (old):
--
@@ -413,7 +416,7 @@ end
local function get_baselevel(head,list,size,direction)
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
- elseif getid(head) == localpar_code and start_of_par(head) then
+ elseif getid(head) == par_code and start_of_par(head) then
direction = getdirection(head)
if direction == lefttoright_code or direction == righttoleft_code then
return direction, true
@@ -943,14 +946,25 @@ local function apply_to_list(list,size,head,pardir)
elseif id == hlist_code or id == vlist_code then
setdirection(current,pardir) -- is this really needed?
elseif id == glue_code then
+ -- Maybe I should also fix dua and dub but on the other hand ... why?
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
- head = insert_node_before(head,current,new_direction(enddir,true))
+ local c = current
+ local p = getprev(c)
+ if p and getid(p) == glue_code and getsubtype(p) == parfillleftskip_code then
+ c = p
+ p = getprev(c)
+ end
+ if p and getid(p) == penalty_code then -- linepenalty
+ c = p
+ end
+ -- there is always a par nodes so head will stay
+ head = insert_node_before(head,c,new_direction(enddir,true))
enddir = false
end
elseif begindir then
- if id == localpar_code and start_of_par(current) then
- -- localpar should always be the 1st node
+ if id == par_code and start_of_par(current) then
+ -- par should always be the 1st node
head, current = insert_node_after(head,current,new_direction(begindir))
begindir = nil
end
diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua
index c4a14846e..3941e65ef 100644
--- a/tex/context/base/mkiv/typo-fln.lua
+++ b/tex/context/base/mkiv/typo-fln.lua
@@ -56,7 +56,7 @@ local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
local kern_code = nodecodes.kern
local glue_code = nodecodes.glue
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local spaceskip_code = nodes.gluecodes.spaceskip
@@ -372,7 +372,7 @@ end
actions[v_default] = actions[v_line]
function firstlines.handler(head)
- if getid(head) == localpar_code and start_of_par(head) then
+ if getid(head) == par_code and start_of_par(head) then
local settings = getprop(head,a_firstline)
if settings then
disableaction("processors","typesetters.firstlines.handler")
diff --git a/tex/context/base/mkiv/typo-itc.mkvi b/tex/context/base/mkiv/typo-itc.mkvi
index 312a2efb4..2bde63857 100644
--- a/tex/context/base/mkiv/typo-itc.mkvi
+++ b/tex/context/base/mkiv/typo-itc.mkvi
@@ -37,8 +37,12 @@
\unexpanded\def\italiccorrection
{\ifnum\c_attr_italics<\plusone\normalitaliccorrection\fi}
+\pushoverloadmode
+
\let\/\italiccorrection
+\popoverloadmode
+
% 1 = end of word
% 2 = end of word and end of a list
diff --git a/tex/context/base/mkiv/typo-lig.mkxl b/tex/context/base/mkiv/typo-lig.mkxl
new file mode 100644
index 000000000..e30774d8e
--- /dev/null
+++ b/tex/context/base/mkiv/typo-lig.mkxl
@@ -0,0 +1,23 @@
+%D \module
+%D [ file=typo-lig,
+%D version=2014.12.01,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Ligatures,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Ligatures}
+
+%D The original macro was mostly used for testing an attribute that blocks ligatures
+%D in the nodemode handler. In \LMTX\ things are done differently.
+
+\unprotect
+
+\permanent\protected\def\noligature{\dontleavehmode\groupedcommandcs\noligaturing\donothing}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua
index 95f9c13fa..4496bd44b 100644
--- a/tex/context/base/mkiv/typo-lin.lua
+++ b/tex/context/base/mkiv/typo-lin.lua
@@ -38,7 +38,7 @@ if not modules then modules = { } end modules ['typo-lin'] = {
-- But, maybe there are good reasons for having just that anchor (mostly for educational purposes
-- I guess.)
--
--- At this stage the localpar node is no longer of any use so we remove it (each line has the
+-- At this stage the par node is no longer of any use so we remove it (each line has the
-- direction attached). We might at some point also strip the disc nodes as they no longer serve
-- a purpose but that can better be a helper. Anchoring left has advantage of keeping page
-- stream.
@@ -65,7 +65,7 @@ local hlist_code = nodecodes.hlist
local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
local linelist_code = listcodes.line
------ localpar_code = nodecodes.localpar
+----- par_code = nodecodes.par
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
local parfillskip_code = gluecodes.parfillskip
@@ -185,7 +185,7 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
id = getid(current)
end
-- no:
- -- if id == localpar_code then
+ -- if id == par_code then
-- head = remove_node(head,head,true)
-- end
local tail = find_tail(head)
diff --git a/tex/context/base/mkiv/typo-mar.mkiv b/tex/context/base/mkiv/typo-mar.mkiv
index 921f1f230..95010ab8e 100644
--- a/tex/context/base/mkiv/typo-mar.mkiv
+++ b/tex/context/base/mkiv/typo-mar.mkiv
@@ -161,8 +161,6 @@
% trialtypesetting: no need for margin stuff while trialing as
% is has no dimensions
-\definesystemconstant{margintext}
-
\newcount\nofmargintexts
\definepagestate[\s!margintext]
@@ -337,7 +335,7 @@
{\endgraf\ifhmode\space\fi}
\appendtoks
- \let\\\spaceorpar
+ \enforced\let\\\spaceorpar
\to \everymargindatacontent
%D Another one:
diff --git a/tex/context/base/mkiv/typo-rub.lua b/tex/context/base/mkiv/typo-rub.lua
index da63d7b64..6c6ab9a33 100644
--- a/tex/context/base/mkiv/typo-rub.lua
+++ b/tex/context/base/mkiv/typo-rub.lua
@@ -63,7 +63,7 @@ local glue_code = nodecodes.glue
local penalty_code = nodecodes.penalty
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local localpar_code = nodecodes.localpar
+local par_code = nodecodes.par
local dir_code = nodecodes.dir
local kerncodes = nodes.kerncodes
@@ -310,7 +310,7 @@ local function whatever(current)
-- go on
elseif id == hlist_code and getwidth(c) == 0 then
-- go on
- elseif id == whatsit_code or id == localpar_code or id == dir_code then
+ elseif id == whatsit_code or id == par_code or id == dir_code then
-- go on
else
l = false